{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "03_pytorch_computer_vision_video.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "toc_visible": true,
      "authorship_tag": "ABX9TyMPumcMDdzwD1Uh4yLbjsvK",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "accelerator": "GPU",
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "452c6620083e4fe79ad988c4e03bae92": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_2ba9710ece4447cc85a60ac113d625a7",
              "IPY_MODEL_ac67fff509494ef89bf39def872f75c5",
              "IPY_MODEL_d9918747d9e84891803b9f7bcc2c0c46"
            ],
            "layout": "IPY_MODEL_56c6bd1514e543c1a6a84b1d78b9ed05"
          }
        },
        "2ba9710ece4447cc85a60ac113d625a7": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_c052fb7f36ce4e1a986966a843d6bfd6",
            "placeholder": "​",
            "style": "IPY_MODEL_b37bb81ea00147a88e6b583c0cb5d3c3",
            "value": "100%"
          }
        },
        "ac67fff509494ef89bf39def872f75c5": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_50361c8ffd78409a91a4a6a2b2469f78",
            "max": 3,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_f354b5dc96384b2aa2e975a84a5d8be3",
            "value": 3
          }
        },
        "d9918747d9e84891803b9f7bcc2c0c46": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_303cfad4137145a5aee3714b965e89ab",
            "placeholder": "​",
            "style": "IPY_MODEL_15da326bed9443c390f550c3e395d62a",
            "value": " 3/3 [00:26&lt;00:00,  7.98s/it]"
          }
        },
        "56c6bd1514e543c1a6a84b1d78b9ed05": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "c052fb7f36ce4e1a986966a843d6bfd6": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "b37bb81ea00147a88e6b583c0cb5d3c3": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "50361c8ffd78409a91a4a6a2b2469f78": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "f354b5dc96384b2aa2e975a84a5d8be3": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "303cfad4137145a5aee3714b965e89ab": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "15da326bed9443c390f550c3e395d62a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "eab7f3156614459ea1fa8a15e32e3873": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_fc81120620dc4407b45aabd76ee21b52",
              "IPY_MODEL_3e8afe57ca034e2e85f90e991334ec4d",
              "IPY_MODEL_d89786d655c048dfa5997ce10e71eb88"
            ],
            "layout": "IPY_MODEL_c84e5af5da0841d6b16131e737f7ae04"
          }
        },
        "fc81120620dc4407b45aabd76ee21b52": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_35cc83324da54f67b81bc99682cd0b66",
            "placeholder": "​",
            "style": "IPY_MODEL_5ee12da0478748518b500de506bf1130",
            "value": "100%"
          }
        },
        "3e8afe57ca034e2e85f90e991334ec4d": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_170eb1aac72c4d66ad647f4ba8381d71",
            "max": 313,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_4496b5cf6c1f40b4a50a0a130e2dc4ac",
            "value": 313
          }
        },
        "d89786d655c048dfa5997ce10e71eb88": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_6a22d5e2a68d43e0ba29db7e0287a2ce",
            "placeholder": "​",
            "style": "IPY_MODEL_b547009c04b2437d9b70629476be5c60",
            "value": " 313/313 [00:00&lt;00:00, 390.53it/s]"
          }
        },
        "c84e5af5da0841d6b16131e737f7ae04": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "35cc83324da54f67b81bc99682cd0b66": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "5ee12da0478748518b500de506bf1130": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "170eb1aac72c4d66ad647f4ba8381d71": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "4496b5cf6c1f40b4a50a0a130e2dc4ac": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "6a22d5e2a68d43e0ba29db7e0287a2ce": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "b547009c04b2437d9b70629476be5c60": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "7fa9e645d1224e20848095ac475b7fb9": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_f3b285dce5944552b7086aab6a3f5173",
              "IPY_MODEL_a3c43e08bc234328a01dfd3c2c39435a",
              "IPY_MODEL_910d36919e354b26aa96653469a74593"
            ],
            "layout": "IPY_MODEL_63934d0b6964446ebc25bb87e0cf14d0"
          }
        },
        "f3b285dce5944552b7086aab6a3f5173": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_2dfe739f14a843d69ffa569c7ba88065",
            "placeholder": "​",
            "style": "IPY_MODEL_63ededa6c647434a839fa235e85ca219",
            "value": "100%"
          }
        },
        "a3c43e08bc234328a01dfd3c2c39435a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_0ddf644c4c5f40bb8131f2182ec9c95c",
            "max": 3,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_f01cb38994b74f73a198b166b62562b4",
            "value": 3
          }
        },
        "910d36919e354b26aa96653469a74593": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_f92ad21514a746eba2d1670ba6558972",
            "placeholder": "​",
            "style": "IPY_MODEL_91e00967267042968c70a214439ef67a",
            "value": " 3/3 [00:20&lt;00:00,  6.68s/it]"
          }
        },
        "63934d0b6964446ebc25bb87e0cf14d0": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "2dfe739f14a843d69ffa569c7ba88065": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "63ededa6c647434a839fa235e85ca219": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "0ddf644c4c5f40bb8131f2182ec9c95c": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "f01cb38994b74f73a198b166b62562b4": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "f92ad21514a746eba2d1670ba6558972": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "91e00967267042968c70a214439ef67a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "3a596cf0f9404d82ad70e8b9f4b1e7ee": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_ba7a0a1af903433a82d884f2d94dc02e",
              "IPY_MODEL_02acd0d634fc4c3aab9ae53d25cc7f6a",
              "IPY_MODEL_cef3ab0d6ff4475aaf7248e213c1eb5b"
            ],
            "layout": "IPY_MODEL_26c959ed124f4586b440323ef07ef3e9"
          }
        },
        "ba7a0a1af903433a82d884f2d94dc02e": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_106cce0a1b674d21aee8b4c95ae53fc1",
            "placeholder": "​",
            "style": "IPY_MODEL_2c43121dfcca4cd6a88770d7f4e19869",
            "value": "  0%"
          }
        },
        "02acd0d634fc4c3aab9ae53d25cc7f6a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "danger",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_a46acba8f3664e10a6c58f5114ff92ec",
            "max": 313,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_03cde3f254604b37a8316e7fb909c986",
            "value": 0
          }
        },
        "cef3ab0d6ff4475aaf7248e213c1eb5b": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_7df2b9c9f4314518b6e14c89add6bb6d",
            "placeholder": "​",
            "style": "IPY_MODEL_5cc320c63cf442c997c6c2f34fbb80f4",
            "value": " 0/313 [00:00&lt;?, ?it/s]"
          }
        },
        "26c959ed124f4586b440323ef07ef3e9": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "106cce0a1b674d21aee8b4c95ae53fc1": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "2c43121dfcca4cd6a88770d7f4e19869": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "a46acba8f3664e10a6c58f5114ff92ec": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "03cde3f254604b37a8316e7fb909c986": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "7df2b9c9f4314518b6e14c89add6bb6d": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "5cc320c63cf442c997c6c2f34fbb80f4": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "86b6aa2170e5416785241eb54d312b24": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_d5f08fedd2084a46a6127d19ec60c8d7",
              "IPY_MODEL_18886c8d03ab4b908554b8e4ede69975",
              "IPY_MODEL_0fd4cfa3085c4cf6b7bd73b8fb956e63"
            ],
            "layout": "IPY_MODEL_aa8f9267d9a849fabb001a9b9fdae854"
          }
        },
        "d5f08fedd2084a46a6127d19ec60c8d7": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_bde0302d529d42b388cc14b76eb8997b",
            "placeholder": "​",
            "style": "IPY_MODEL_04434f22ab084e2aa4291eb76dd8caec",
            "value": "100%"
          }
        },
        "18886c8d03ab4b908554b8e4ede69975": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_bbeeb4d3f59b48ac9443d29200de1868",
            "max": 313,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_7ca50270baed4c069bec8e49f68437ef",
            "value": 313
          }
        },
        "0fd4cfa3085c4cf6b7bd73b8fb956e63": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_deec91f27061464995ea185dac966197",
            "placeholder": "​",
            "style": "IPY_MODEL_31e634fc47d5405a9751588e659db601",
            "value": " 313/313 [00:00&lt;00:00, 387.47it/s]"
          }
        },
        "aa8f9267d9a849fabb001a9b9fdae854": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "bde0302d529d42b388cc14b76eb8997b": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "04434f22ab084e2aa4291eb76dd8caec": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "bbeeb4d3f59b48ac9443d29200de1868": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "7ca50270baed4c069bec8e49f68437ef": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "deec91f27061464995ea185dac966197": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "31e634fc47d5405a9751588e659db601": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "68711c9d9d1642fcaa2b2e315bfd397d": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_04aea2c27e7d474c9b90d0652a9c1cf5",
              "IPY_MODEL_a740c3de6c59407d81ddf303cfca6477",
              "IPY_MODEL_5acae86e9528489a9ab1c644669732c2"
            ],
            "layout": "IPY_MODEL_2c2a8fa51d7a4a4db851f95e5ea89fa9"
          }
        },
        "04aea2c27e7d474c9b90d0652a9c1cf5": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_e6a36256789748a3850fe3d011be8849",
            "placeholder": "​",
            "style": "IPY_MODEL_0298028987a14b69a1170c517aed5f5a",
            "value": "100%"
          }
        },
        "a740c3de6c59407d81ddf303cfca6477": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_94aaeb0786484fd38fbb10380a7d891c",
            "max": 3,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_9bd2f35f1aa649d7820c5bb47896dd1a",
            "value": 3
          }
        },
        "5acae86e9528489a9ab1c644669732c2": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_fc46fa93b44b4212aa25158905ac411b",
            "placeholder": "​",
            "style": "IPY_MODEL_c4fb9e39bef348f8bbee3cc67195013a",
            "value": " 3/3 [00:32&lt;00:00, 10.97s/it]"
          }
        },
        "2c2a8fa51d7a4a4db851f95e5ea89fa9": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "e6a36256789748a3850fe3d011be8849": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "0298028987a14b69a1170c517aed5f5a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "94aaeb0786484fd38fbb10380a7d891c": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "9bd2f35f1aa649d7820c5bb47896dd1a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "fc46fa93b44b4212aa25158905ac411b": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "c4fb9e39bef348f8bbee3cc67195013a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "b20785d11eac4ecd88c2d1fcf5f87e99": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_4a8c9a109c324cb6b285fe655a7b7a52",
              "IPY_MODEL_1de0bde77ecd4a5aa2831ac3e767522a",
              "IPY_MODEL_c292425b6491436bb09d6b526a3f05d3"
            ],
            "layout": "IPY_MODEL_ef71a3d209ef4e80863df4076f3fc6b3"
          }
        },
        "4a8c9a109c324cb6b285fe655a7b7a52": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_48df394b8e0244fb9a55ce99908a6857",
            "placeholder": "​",
            "style": "IPY_MODEL_006deca9eded4d18881cc81ec34650a3",
            "value": "100%"
          }
        },
        "1de0bde77ecd4a5aa2831ac3e767522a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_74a40d51368b4f00a83917bee93cab1a",
            "max": 313,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_40e05f64efd744afbc227e7bf399a8e7",
            "value": 313
          }
        },
        "c292425b6491436bb09d6b526a3f05d3": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_d78d6d8d2d9a4611aecb70126668c237",
            "placeholder": "​",
            "style": "IPY_MODEL_002fad04387e410e9907948bbe1975b3",
            "value": " 313/313 [00:01&lt;00:00, 319.98it/s]"
          }
        },
        "ef71a3d209ef4e80863df4076f3fc6b3": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "48df394b8e0244fb9a55ce99908a6857": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "006deca9eded4d18881cc81ec34650a3": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "74a40d51368b4f00a83917bee93cab1a": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "40e05f64efd744afbc227e7bf399a8e7": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "d78d6d8d2d9a4611aecb70126668c237": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "002fad04387e410e9907948bbe1975b3": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "9ab6303c323a4e23857567776bc0d20d": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_b590346c9b654f42b2155bb94c16eae6",
              "IPY_MODEL_3fec6a3f89c9452ebc9f3ebf6bface3a",
              "IPY_MODEL_17df0b9ca3ca4cc1a26fe432c5997f3b"
            ],
            "layout": "IPY_MODEL_825aae30ddcb49458ec0ec780342d013"
          }
        },
        "b590346c9b654f42b2155bb94c16eae6": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_9b5740eb07014edb9a99b2fb863751f5",
            "placeholder": "​",
            "style": "IPY_MODEL_49bd278666eb4bee88e1f7d358009589",
            "value": "Making predictions...: 100%"
          }
        },
        "3fec6a3f89c9452ebc9f3ebf6bface3a": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_dbaedbc56495423dab883581485a9647",
            "max": 313,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_1e8e68b35eb24de18b27030ebcedcb49",
            "value": 313
          }
        },
        "17df0b9ca3ca4cc1a26fe432c5997f3b": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_7586aa9081074619b138b40a14537210",
            "placeholder": "​",
            "style": "IPY_MODEL_bc263e0135f44bffa75ae95f63be97b7",
            "value": " 313/313 [00:00&lt;00:00, 337.25it/s]"
          }
        },
        "825aae30ddcb49458ec0ec780342d013": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "9b5740eb07014edb9a99b2fb863751f5": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "49bd278666eb4bee88e1f7d358009589": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "dbaedbc56495423dab883581485a9647": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "1e8e68b35eb24de18b27030ebcedcb49": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "7586aa9081074619b138b40a14537210": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "bc263e0135f44bffa75ae95f63be97b7": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "eddf525370cc47dc8c39a683157d1349": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_3dc582db727f42cb952084739ee3fcf7",
              "IPY_MODEL_b89ea56117304c299214076f7acff99f",
              "IPY_MODEL_3c00bb6d32ef4031b01a756bf3eb9a76"
            ],
            "layout": "IPY_MODEL_a1ea8ec4a407495aa9395f279889cff5"
          }
        },
        "3dc582db727f42cb952084739ee3fcf7": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_90e5c0cf18c34a88bfc7275bb5fc96a2",
            "placeholder": "​",
            "style": "IPY_MODEL_e1b43099620b497eacc22b708bf4c2ff",
            "value": "100%"
          }
        },
        "b89ea56117304c299214076f7acff99f": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "success",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_1560cfbd3ba641bdb8acc89f7f17fb2d",
            "max": 313,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_e30a4eed4e9145dc9597cb55100bec57",
            "value": 313
          }
        },
        "3c00bb6d32ef4031b01a756bf3eb9a76": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_7f792d4491084829999e5540094cb85d",
            "placeholder": "​",
            "style": "IPY_MODEL_898759c1d24645e2b6678011cb00a76e",
            "value": " 313/313 [00:01&lt;00:00, 164.66it/s]"
          }
        },
        "a1ea8ec4a407495aa9395f279889cff5": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "90e5c0cf18c34a88bfc7275bb5fc96a2": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "e1b43099620b497eacc22b708bf4c2ff": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "1560cfbd3ba641bdb8acc89f7f17fb2d": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "e30a4eed4e9145dc9597cb55100bec57": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "7f792d4491084829999e5540094cb85d": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "898759c1d24645e2b6678011cb00a76e": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        }
      }
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/mrdbourke/pytorch-deep-learning/blob/main/video_notebooks/03_pytorch_computer_vision_video.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# PyTorch Computer Vision\n",
        "\n",
        "* See reference notebook - https://github.com/mrdbourke/pytorch-deep-learning/blob/main/03_pytorch_computer_vision.ipynb \n",
        "* See reference online book - https://www.learnpytorch.io/03_pytorch_computer_vision/"
      ],
      "metadata": {
        "id": "SC8TASYkfG8P"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 0. Computer vision libaries in PyTorch\n",
        "\n",
        "* [`torchvision`](https://www.learnpytorch.io/03_pytorch_computer_vision/) - base domain library for PyTorch computer vision\n",
        "* `torchvision.datasets` - get datasets and data loading functions for computer vision here\n",
        "* `torchvision.models` - get pretrained computer vision models that you can leverage for your own problems\n",
        "* `torchvision.transforms` - functions for manipulating your vision data (images) to be suitable for use with an ML model\n",
        "* `torch.utils.data.Dataset` - Base dataset class for PyTorch.\n",
        "* `torch.utils.data.DataLoader` - Creates a Python iterable over a dataset"
      ],
      "metadata": {
        "id": "hIVes8dHfY4d"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Import PyTorch\n",
        "import torch\n",
        "from torch import nn\n",
        "\n",
        "# Import torchvision\n",
        "import torchvision\n",
        "from torchvision import datasets\n",
        "from torchvision import transforms\n",
        "from torchvision.transforms import ToTensor\n",
        "\n",
        "# Import matplotlib for visualization\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "# Check versions\n",
        "print(torch.__version__)\n",
        "print(torchvision.__version__)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "j71QICM3gOZs",
        "outputId": "73a9d45e-ffdd-4b15-8266-5e777dc951ba"
      },
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "1.10.0+cu111\n",
            "0.11.1+cu111\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 1. Getting a dataset\n",
        "\n",
        "The dataset we'll be using is FashionMNIST from torchvision.datasets - https://pytorch.org/vision/stable/generated/torchvision.datasets.FashionMNIST.html#torchvision.datasets.FashionMNIST "
      ],
      "metadata": {
        "id": "n8E6wzT5hHsz"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Setup training data\n",
        "from torchvision import datasets\n",
        "train_data = datasets.FashionMNIST(\n",
        "    root=\"data\", # where to download data to?\n",
        "    train=True, # do we want the training dataset?\n",
        "    download=True, # do we want to download yes/no?\n",
        "    transform=torchvision.transforms.ToTensor(), # how do we want to transform the data?\n",
        "    target_transform=None # how do we want to transform the labels/targets?\n",
        ")\n",
        "\n",
        "test_data = datasets.FashionMNIST(\n",
        "    root=\"data\",\n",
        "    train=False,\n",
        "    download=True,\n",
        "    transform=ToTensor(),\n",
        "    target_transform=None\n",
        ")"
      ],
      "metadata": {
        "id": "WQdGrIWTi4Th"
      },
      "execution_count": 2,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "len(train_data), len(test_data)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "tIUdwIFfkFyM",
        "outputId": "daac52dc-ce02-425d-8602-fdb99fd63c29"
      },
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(60000, 10000)"
            ]
          },
          "metadata": {},
          "execution_count": 3
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# See the first training example\n",
        "image, label = train_data[0]\n",
        "image, label"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "NQhaUN1RkFwF",
        "outputId": "05055403-c22d-476a-f90c-613f3daccf29"
      },
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(tensor([[[0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0039, 0.0000, 0.0000, 0.0510,\n",
              "           0.2863, 0.0000, 0.0000, 0.0039, 0.0157, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0039, 0.0039, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0118, 0.0000, 0.1412, 0.5333,\n",
              "           0.4980, 0.2431, 0.2118, 0.0000, 0.0000, 0.0000, 0.0039, 0.0118,\n",
              "           0.0157, 0.0000, 0.0000, 0.0118],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0235, 0.0000, 0.4000, 0.8000,\n",
              "           0.6902, 0.5255, 0.5647, 0.4824, 0.0902, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0471, 0.0392, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.6078, 0.9255,\n",
              "           0.8118, 0.6980, 0.4196, 0.6118, 0.6314, 0.4275, 0.2510, 0.0902,\n",
              "           0.3020, 0.5098, 0.2824, 0.0588],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0039, 0.0000, 0.2706, 0.8118, 0.8745,\n",
              "           0.8549, 0.8471, 0.8471, 0.6392, 0.4980, 0.4745, 0.4784, 0.5725,\n",
              "           0.5529, 0.3451, 0.6745, 0.2588],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0039, 0.0039, 0.0039, 0.0000, 0.7843, 0.9098, 0.9098,\n",
              "           0.9137, 0.8980, 0.8745, 0.8745, 0.8431, 0.8353, 0.6431, 0.4980,\n",
              "           0.4824, 0.7686, 0.8980, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.7176, 0.8824, 0.8471,\n",
              "           0.8745, 0.8941, 0.9216, 0.8902, 0.8784, 0.8706, 0.8784, 0.8667,\n",
              "           0.8745, 0.9608, 0.6784, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.7569, 0.8941, 0.8549,\n",
              "           0.8353, 0.7765, 0.7059, 0.8314, 0.8235, 0.8275, 0.8353, 0.8745,\n",
              "           0.8627, 0.9529, 0.7922, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0039, 0.0118, 0.0000, 0.0471, 0.8588, 0.8627, 0.8314,\n",
              "           0.8549, 0.7529, 0.6627, 0.8902, 0.8157, 0.8549, 0.8784, 0.8314,\n",
              "           0.8863, 0.7725, 0.8196, 0.2039],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0235, 0.0000, 0.3882, 0.9569, 0.8706, 0.8627,\n",
              "           0.8549, 0.7961, 0.7765, 0.8667, 0.8431, 0.8353, 0.8706, 0.8627,\n",
              "           0.9608, 0.4667, 0.6549, 0.2196],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0157, 0.0000, 0.0000, 0.2157, 0.9255, 0.8941, 0.9020,\n",
              "           0.8941, 0.9412, 0.9098, 0.8353, 0.8549, 0.8745, 0.9176, 0.8510,\n",
              "           0.8510, 0.8196, 0.3608, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0039, 0.0157, 0.0235, 0.0275, 0.0078, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.9294, 0.8863, 0.8510, 0.8745,\n",
              "           0.8706, 0.8588, 0.8706, 0.8667, 0.8471, 0.8745, 0.8980, 0.8431,\n",
              "           0.8549, 1.0000, 0.3020, 0.0000],\n",
              "          [0.0000, 0.0118, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.2431, 0.5686, 0.8000, 0.8941, 0.8118, 0.8353, 0.8667,\n",
              "           0.8549, 0.8157, 0.8275, 0.8549, 0.8784, 0.8745, 0.8588, 0.8431,\n",
              "           0.8784, 0.9569, 0.6235, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0706, 0.1725, 0.3216, 0.4196,\n",
              "           0.7412, 0.8941, 0.8627, 0.8706, 0.8510, 0.8863, 0.7843, 0.8039,\n",
              "           0.8275, 0.9020, 0.8784, 0.9176, 0.6902, 0.7373, 0.9804, 0.9725,\n",
              "           0.9137, 0.9333, 0.8431, 0.0000],\n",
              "          [0.0000, 0.2235, 0.7333, 0.8157, 0.8784, 0.8667, 0.8784, 0.8157,\n",
              "           0.8000, 0.8392, 0.8157, 0.8196, 0.7843, 0.6235, 0.9608, 0.7569,\n",
              "           0.8078, 0.8745, 1.0000, 1.0000, 0.8667, 0.9176, 0.8667, 0.8275,\n",
              "           0.8627, 0.9098, 0.9647, 0.0000],\n",
              "          [0.0118, 0.7922, 0.8941, 0.8784, 0.8667, 0.8275, 0.8275, 0.8392,\n",
              "           0.8039, 0.8039, 0.8039, 0.8627, 0.9412, 0.3137, 0.5882, 1.0000,\n",
              "           0.8980, 0.8667, 0.7373, 0.6039, 0.7490, 0.8235, 0.8000, 0.8196,\n",
              "           0.8706, 0.8941, 0.8824, 0.0000],\n",
              "          [0.3843, 0.9137, 0.7765, 0.8235, 0.8706, 0.8980, 0.8980, 0.9176,\n",
              "           0.9765, 0.8627, 0.7608, 0.8431, 0.8510, 0.9451, 0.2549, 0.2863,\n",
              "           0.4157, 0.4588, 0.6588, 0.8588, 0.8667, 0.8431, 0.8510, 0.8745,\n",
              "           0.8745, 0.8784, 0.8980, 0.1137],\n",
              "          [0.2941, 0.8000, 0.8314, 0.8000, 0.7569, 0.8039, 0.8275, 0.8824,\n",
              "           0.8471, 0.7255, 0.7725, 0.8078, 0.7765, 0.8353, 0.9412, 0.7647,\n",
              "           0.8902, 0.9608, 0.9373, 0.8745, 0.8549, 0.8314, 0.8196, 0.8706,\n",
              "           0.8627, 0.8667, 0.9020, 0.2627],\n",
              "          [0.1882, 0.7961, 0.7176, 0.7608, 0.8353, 0.7725, 0.7255, 0.7451,\n",
              "           0.7608, 0.7529, 0.7922, 0.8392, 0.8588, 0.8667, 0.8627, 0.9255,\n",
              "           0.8824, 0.8471, 0.7804, 0.8078, 0.7294, 0.7098, 0.6941, 0.6745,\n",
              "           0.7098, 0.8039, 0.8078, 0.4510],\n",
              "          [0.0000, 0.4784, 0.8588, 0.7569, 0.7020, 0.6706, 0.7176, 0.7686,\n",
              "           0.8000, 0.8235, 0.8353, 0.8118, 0.8275, 0.8235, 0.7843, 0.7686,\n",
              "           0.7608, 0.7490, 0.7647, 0.7490, 0.7765, 0.7529, 0.6902, 0.6118,\n",
              "           0.6549, 0.6941, 0.8235, 0.3608],\n",
              "          [0.0000, 0.0000, 0.2902, 0.7412, 0.8314, 0.7490, 0.6863, 0.6745,\n",
              "           0.6863, 0.7098, 0.7255, 0.7373, 0.7412, 0.7373, 0.7569, 0.7765,\n",
              "           0.8000, 0.8196, 0.8235, 0.8235, 0.8275, 0.7373, 0.7373, 0.7608,\n",
              "           0.7529, 0.8471, 0.6667, 0.0000],\n",
              "          [0.0078, 0.0000, 0.0000, 0.0000, 0.2588, 0.7843, 0.8706, 0.9294,\n",
              "           0.9373, 0.9490, 0.9647, 0.9529, 0.9569, 0.8667, 0.8627, 0.7569,\n",
              "           0.7490, 0.7020, 0.7137, 0.7137, 0.7098, 0.6902, 0.6510, 0.6588,\n",
              "           0.3882, 0.2275, 0.0000, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.1569,\n",
              "           0.2392, 0.1725, 0.2824, 0.1608, 0.1373, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000],\n",
              "          [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
              "           0.0000, 0.0000, 0.0000, 0.0000]]]), 9)"
            ]
          },
          "metadata": {},
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "class_names = train_data.classes\n",
        "class_names"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "LIEAQ-FkkFuA",
        "outputId": "dad9171c-caf2-4382-bb28-22d90baeeb8e"
      },
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "['T-shirt/top',\n",
              " 'Trouser',\n",
              " 'Pullover',\n",
              " 'Dress',\n",
              " 'Coat',\n",
              " 'Sandal',\n",
              " 'Shirt',\n",
              " 'Sneaker',\n",
              " 'Bag',\n",
              " 'Ankle boot']"
            ]
          },
          "metadata": {},
          "execution_count": 5
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "class_to_idx = train_data.class_to_idx\n",
        "class_to_idx"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4WNmPq7kkFE4",
        "outputId": "1d0903ed-32e1-4543-896b-4112f31fb7e3"
      },
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'Ankle boot': 9,\n",
              " 'Bag': 8,\n",
              " 'Coat': 4,\n",
              " 'Dress': 3,\n",
              " 'Pullover': 2,\n",
              " 'Sandal': 5,\n",
              " 'Shirt': 6,\n",
              " 'Sneaker': 7,\n",
              " 'T-shirt/top': 0,\n",
              " 'Trouser': 1}"
            ]
          },
          "metadata": {},
          "execution_count": 6
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "train_data.targets"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "1SwNztlVkFCY",
        "outputId": "ce443d4f-7286-40c2-f5dd-a981692be6b0"
      },
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([9, 0, 0,  ..., 3, 0, 5])"
            ]
          },
          "metadata": {},
          "execution_count": 7
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 1.1 Check input and output shapes of data"
      ],
      "metadata": {
        "id": "JvAEJBnOvTvS"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Check the shape of our image\n",
        "print(f\"Image shape: {image.shape} -> [color_channels, height, width]\") \n",
        "print(f\"Image label: {class_names[label]}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "QGz6d6wnkFAG",
        "outputId": "20bd7758-95a0-44a6-92b8-6d3fc5273fc6"
      },
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Image shape: torch.Size([1, 28, 28]) -> [color_channels, height, width]\n",
            "Image label: Ankle boot\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 1.2 Visualizing our data"
      ],
      "metadata": {
        "id": "fWmrGoIukE6_"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import matplotlib.pyplot as plt\n",
        "image, label = train_data[0]\n",
        "print(f\"Image shape: {image.shape}\")\n",
        "plt.imshow(image.squeeze())\n",
        "plt.title(label);\n",
        "# image"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 299
        },
        "id": "TemhJeWzkE4L",
        "outputId": "1f78e3a7-f9b9-4b26-a318-0e6d95350953"
      },
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Image shape: torch.Size([1, 28, 28])\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "plt.imshow(image.squeeze(), cmap=\"gray\")\n",
        "plt.title(class_names[label]);\n",
        "plt.axis(False);"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 264
        },
        "id": "KFBjs5GxwNBx",
        "outputId": "479b7495-265c-43b1-fb30-bb2c9072a521"
      },
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOcAAAD3CAYAAADmIkO7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAN10lEQVR4nO3da2yW9RnH8d9lq2BLLXLooOhEBSbbohjPCsbz6cViUHHLMiXMvfDNDonJtszMLM5hdMlcosmSscwXbC57AYnG0/SFyZaCyoiDLeUFRYFSrSCHlXKQw38v+rB0Te/rwj52varfT9KE8vP/9H6eh5932yv/+7ZSigDkc8pYHwCA4VFOICnKCSRFOYGkKCeQFOUEkqKcCZlZMbM5nzQLHnOpmf2t/qPD/wvlHEVm9oaZ7TGzCWN9LKPFzK4zs+6xPo7PIso5SsxstqRFkoqkr43pwWBcopyj5z5JayU9K+n+wYGZPWtmz5jZi2bWZ2Zvmtn5wz2ImS00s+1mdt0w2QQz+6WZbTOzXjP7jZmd7hyTmdnTZrbPzDaZ2Y2DgnYze97MdpvZZjP7zpCv85SZ9dQ+nqr9XbOklyW1m9n+2kf7J3mRUI1yjp77JP2h9nGrmX1hSP51ST+TdKakzZIeG/oAZnabpOck3VVKeWOYr/G4pHmSFkiaI2mWpJ86x3SFpC5J0yQ9ImmVmU2pZX+S1C2pXdLdkn5hZjfUsp9IurL2dS6SdLmkh0sp/ZJul9RTSplU++hxvj4+iVIKH5/yh6SFko5Imlb7fJOkHwzKn5W0YtDnd0jaNOjzIunHkrZK+uqQxy4aKKJJ6pd0/qDsKknvVhzTUkk9kmzQ370l6VuSzpZ0TFLLoGy5pGdrf+6SdMeg7FZJ79X+fJ2k7rF+zT+LH5w5R8f9kv5SStlV+/yPGvKtraQPBv35gKRJQ/LvS/pzKeWfFV9juqQmSX83s71mtlfSK7W/r7Kj1BpVs1UDZ8p2SbtLKX1Dslm1P7fXPh+6DqOocawP4LOm9jPfEkkNZnaigBMkTTazi0op/zjJh7pH0u/MrLuU8uth8l2SDkr6Sillx0k+5iwzs0EF/aKk5zVwRp1iZi2DCvpFSScet0fSOZL+NSg78e0r25pGCWfOT9+dGvgW8csa+BltgaT5kv6qgZ9DT1aPpBslfc/MHhwallKOS/qtpF+ZWZskmdksM7vVecw2Sd81s1PN7J7acb1UStkuqUPScjObaGYXSvq2pJW1dc9JetjMppvZNA38XHsi65U01cxaP8Fzw0mgnJ+++yX9vpSyrZTywYkPSU9L+qaZnfR3K6WUbRoo6I/M7IFh/pMfauCXSWvN7N+SXpf0Jech35Q0VwNn3cck3V1K+aiWfUPSbA38T2G1pEdKKa/Xsp9LWidpg6SNktbX/k6llE0aKO+W2rfXfLv7KbH//REEQBacOYGkKCeQFOUEkqKcQFLubw7NjN8WAaOslGLD/T1nTiApygkkRTmBpCgnkBTlBJKinEBSlBNIinICSVFOICnKCSRFOYGkKCeQFOUEkqKcQFKUE0iKcgJJUU4gKcoJJEU5gaQoJ5AU5QSSopxAUtwCMBmzYa+S+F/13tumpaXFzRcuXFiZvfzyy3V97ei5NTQ0VGZHjx6t62vXKzp2z0jfM86cQFKUE0iKcgJJUU4gKcoJJEU5gaQoJ5AUc85kTjnF///lsWPH3HzOnDlu/sADD7j5wYMHK7P+/n537aFDh9z8rbfecvN6ZpnRHDJ6XaP19RybN7/1cOYEkqKcQFKUE0iKcgJJUU4gKcoJJEU5gaSYcyYTzcSiOecNN9zg5jfddJObd3d3V2YTJkxw1zY1Nbn5zTff7OYrVqyozHp7e9210Z7J6HWLTJo0qTI7fvy4u/bAgQMj+pqcOYGkKCeQFOUEkqKcQFKUE0iKcgJJUU4gKeacyXz88cd1rb/sssvcfPbs2W7uzVmjPZGvvvqqm1988cVu/sQTT1Rm69atc9du3LjRzTs7O9388ssvd3Pvde3o6HDXrlmzxs2rcOYEkqKcQFKUE0iKcgJJUU4gKcoJJMUoZQx4l2GMtj5F264uvfRSN+/r63Pz5ubmymzevHnu2ih/++233Xzz5s2VmbdlS5KuuuoqN1+8eLGbHzlyxM29Y48uN3r48GE3r8KZE0iKcgJJUU4gKcoJJEU5gaQoJ5AU5QSSMm+uZmb+0O1zKrpdXD2iOefatWvdPNoSFvGeW3QbvHq3u3m3EIwuP7l+/Xo392aoUvzcbrvttsrsvPPOc9fOmjXLzUspw77onDmBpCgnkBTlBJKinEBSlBNIinICSVFOICn2c45ANIscTXv27HHzmTNnuvnBgwfd3LvNX2Oj/88l2nPpzTEl6fTTT6/MojnnokWL3Pzqq6928+iyn21tbZXZK6+84q4dKc6cQFKUE0iKcgJJUU4gKcoJJEU5gaQoJ5AUc85xpqmpyc2jeV2UHzhwoDLbt2+fu/ajjz5y82ivabC32F0bPa/odTt27Jibe3PWs88+2107Upw5gaQoJ5AU5QSSopxAUpQTSIpyAklRTiAp5pwjUO/MzZupRXsi29vb3Ty6F2SUe/s5o+vSejNSSZo8ebKbe3PSaE552mmnuXl0X9LW1lY337BhQ2UWvWfRPVOrcOYEkqKcQFKUE0iKcgJJUU4gKcoJJMUoZQSiS2M2NDS4uTdKuffee921M2bMcPOdO3e6uXf5ScnfGtXc3OyujbZORaMYb4xz5MgRd2102c7oeU+dOtXNn3nmmcpswYIF7tro2Kpw5gSSopxAUpQTSIpyAklRTiApygkkRTmBpCy4HOHY3esusWhudfTo0RE/9hVXXOHmL774optHt/irZwbb0tLiro1u8RddOvPUU08dUSbFM9jo1okR77k9+eST7tqVK1e6eSll2D2InDmBpCgnkBTlBJKinEBSlBNIinICSVFOIKlR3c/pXUIymrdFl5eMLk/p7f/z9iyejHrmmJGXXnrJzfv7+908mnNGl5D05t7RXtHoPZ04caKbR3s261kbvefRsV944YWVWXRrxJHizAkkRTmBpCgnkBTlBJKinEBSlBNIinICSdU156xnb+BozgpH27XXXuvmd911l5tfc801lVl0G71oT2Q0x4z2onrvWXRs0b8H77q0kj8Hja4VHB1bJHrd9u/fX5ktXrzYXfvCCy+M6Jg4cwJJUU4gKcoJJEU5gaQoJ5AU5QSSopxAUmmvWztlyhQ3b29vd/O5c+eOeG00t5o3b56bHz582M29varRvsToPpM9PT1uHl3/1Zv3RfewjO6/2dTU5OYdHR2V2aRJk9y10ew52s8Z7cn0Xrfe3l537fz5892c69YC4wzlBJKinEBSlBNIinICSVFOIKm6RilXXnml++CPPvpoZTZ9+nR37eTJk93c29ok+duX9u7d666NtrNFI4FopOBd1jO6tGVnZ6ebL1myxM3XrVvn5t5t/s4880x37ezZs908smXLlsosuv1gX1+fm0dbyqIRlTfKOeOMM9y10b8XRinAOEM5gaQoJ5AU5QSSopxAUpQTSIpyAkm5c87GxkZ3zrlmzRr3wWfOnFmZRXPKKK/nUojRJRyjWWO9WltbK7Np06a5a5cuXermt9xyi5s/+OCDbu5tOTt06JC79t1333Vzb44p+dv86t2uFm2Vi+ao3vpoO9o555zj5sw5gXGGcgJJUU4gKcoJJEU5gaQoJ5AU5QSScuecy5Ytc+ecjz/+uPvgXV1dlVl0qcMoj24n54lmXt4cUpK2b9/u5tHlKb29rN5lMyVpxowZbn7nnXe6uXebPcnfkxm9J5dccklduffcozlm9LpFt/iLeHtwo39P0b7nbdu2MecExhPKCSRFOYGkKCeQFOUEkqKcQFKUE0iq0Qs//PBDd3E07/P2yEW3yYseO5q5eXOt6Dqju3fvdvOtW7e6eXRs3n7RaM9kdE3d1atXu/nGjRvd3JtzRrdljGaR0fWCvdsfRs872lMZzSKj9d6cM5qhRreMrMKZE0iKcgJJUU4gKcoJJEU5gaQoJ5CUO0rZsWOHu9jbbiZJ3d3dlVlzc7O7NrpEZPRr+V27dlVmO3fudNc2NrovS7hdLfq1vbdtK7pEY7Q1ynvekjR//nw37+/vr8yi8daePXvcPHrdvGP3xixSPGqJ1ke3APS26u3bt89du2DBAjevwpkTSIpyAklRTiApygkkRTmBpCgnkBTlBJJyB3rvvPOOu3jVqlVuvmzZssosunxkdLu4aGuVt20rmkNGM69oi1B0i0Fvu1x068NothzdGvH9998f8eNHxxbNh+t5z+rdjlbPdjXJn6Oee+657tre3l43r8KZE0iKcgJJUU4gKcoJJEU5gaQoJ5AU5QSScm8BaGb+UC1w++23V2YPPfSQu7atrc3No32L3lwrmtdFc8pozhnN+7zH9y7BKMVzzmiGG+Xec4vWRsce8daPdFZ4QvSeRZfG9PZzbtiwwV27ZMkSNy+lcAtAYDyhnEBSlBNIinICSVFOICnKCSRFOYGk3DlnQ0ODO1SLZkP1uP766918+fLlbu7NSVtbW9210bVhozloNOeM5qye6LaM0Rw0uhax957u37/fXRu9LhHv2KP9ltE+1ug9fe2119y8s7OzMuvo6HDXRphzAuMM5QSSopxAUpQTSIpyAklRTiApygkkNar7ObO64IIL3Lzee4OeddZZbv7ee+9VZtE8r6ury80x/jDnBMYZygkkRTmBpCgnkBTlBJKinEBSn8tRCpAJoxRgnKGcQFKUE0iKcgJJUU4gKcoJJEU5gaQoJ5AU5QSSopxAUpQTSIpyAklRTiApygkkRTmBpNz9nADGDmdOICnKCSRFOYGkKCeQFOUEkqKcQFL/AZim/CVqjnvWAAAAAElFTkSuQmCC\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Plot more images\n",
        "# torch.manual_seed(42)\n",
        "fig = plt.figure(figsize=(9, 9))\n",
        "rows, cols = 4, 4\n",
        "for i in range(1, rows*cols+1):\n",
        "  random_idx = torch.randint(0, len(train_data), size=[1]).item()\n",
        "  img, label = train_data[random_idx]\n",
        "  fig.add_subplot(rows, cols, i)\n",
        "  plt.imshow(img.squeeze(), cmap=\"gray\")\n",
        "  plt.title(class_names[label])\n",
        "  plt.axis(False);"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 536
        },
        "id": "NmUDqnawwM_o",
        "outputId": "363bab43-6362-41f1-e161-953110526783"
      },
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 648x648 with 16 Axes>"
            ],
            "image/png": "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0y1atHA6Pt+GG27o6jp06OD0woULIYRYdeoybXB8Lo7l/+qrrzLfO3z4cKfPOOMMp9da638/s1deeaWr69u3r9M/+clPnN5ss82cPuWUU5weMWJEWn788cdd3TrrrJPV7BStBAghhBAFRZMAIYQQoqBoEiCEEEIUFPkEVEhWDGneFpIcT5p3/OGHH56Wp06d6urGjRtXwxY3ftgHYN1113U6vm4cm895uz/55BOnDznkEKcPOOCAtPzBBx+U/RwA+Pjjj53u3Lmz0+zLENsSW7du7er4Owkhakdd+gTE72cfgK5duzodj8sAsMUWWzjN+fxvvfXWtPyrX/3K1Z111llOx9umV0fHjh2dXrZsWVrm35PPPvss81wr0UqAEEIIUVA0CRBCCCEKiiYBQgghREEphE9AfdmOanu+vPe2bds2LbN9ujkRx9ECwLbbbuv0tGnTyr73888/d5rtd5xPO7aTsX2NY/nj61/duZYvX+50vOfB4MGDy9YBVfMdCCEqIytnP9vHOWaex42Y3Xff3el99tnHaX52J02a5HS81wkA3H333Wl5l112yWwnc/DBBzs9ZcoUp+Mxi32WOIdKObQSIIQQQhQUTQKEEEKIgqJJgBBCCFFQ5BNAPPXUU07/5S9/cXrmzJlOx7YltjtxbP8GG2zg9J/+9CenX331VaffeOONtMy2oObEm2++6fTEiROd7tGjR1r+8ssvXR3nCWjZsqXTnAc83o+b6zjun30V2EdgvfXWczreS2D+/Pmu7t1334WoW/je5+3rXpd0797dad7nnfeZyIL7WV6u+rjf8XhW09jw5g5flywfAMDH+g8bNszV8Tjer18/pzm2f7vttnM6HmfY74jhz2b/qPvvv9/pxYsXp+U+ffq4OvkECCGEECITTQKEEEKIglI4cwDDYWK8nMwpIU899dSy5+LtY/lzOcyPl+623HJLpzn0JOvczYl9993X6ddeey0t8/3iZb9Kl1az3svL/QwvMcbvf+aZZ2r8uWLVqO3yfxxSxaGlbL7hdK987y+66KKyn8NmQu6TrHv16uX0Hnvs4fTAgQPT8oQJE1zdbbfdVrYdzY0sMy+birbaaiunN954Y6fjZfd463Kgalrz559/3unYbAtUNRfstNNO3PSy8Nj30UcfOc3jfjzmcLt5K/RyaCVACCGEKCiaBAghhBAFRZMAIYQQ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\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "Do you think these items of clothing (images) could be modelled with pure linear lines? Or do you think we'll need non-linearities?"
      ],
      "metadata": {
        "id": "O11qxz6xzljb"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "train_data, test_data"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "XNYvd006z0hW",
        "outputId": "378af9e0-2d33-4608-b70d-038f42f8a30b"
      },
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(Dataset FashionMNIST\n",
              "     Number of datapoints: 60000\n",
              "     Root location: data\n",
              "     Split: Train\n",
              "     StandardTransform\n",
              " Transform: ToTensor(), Dataset FashionMNIST\n",
              "     Number of datapoints: 10000\n",
              "     Root location: data\n",
              "     Split: Test\n",
              "     StandardTransform\n",
              " Transform: ToTensor())"
            ]
          },
          "metadata": {},
          "execution_count": 12
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 2. Prepare DataLoader\n",
        "\n",
        "Right now, our data is in the form of PyTorch Datasets.\n",
        "\n",
        "DataLoader turns our dataset into a Python iterable.\n",
        "\n",
        "More specifically, we want to turn our data into batches (or mini-batches).\n",
        "\n",
        "Why would we do this?\n",
        "\n",
        "1. It is more computationally efficient, as in, your computing hardware may not be able to look (store in memory) at 60000 images in one hit. So we break it down to 32 images at a time (batch size of 32). \n",
        "2. It gives our neural network more chances to update its gradients per epoch.\n",
        "\n",
        "For more on mini-batches, see here: https://youtu.be/l4lSUAcvHFs"
      ],
      "metadata": {
        "id": "giVdZx6VwM9W"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from torch.utils.data import DataLoader\n",
        "\n",
        "# Setup the batch size hyperparameter\n",
        "BATCH_SIZE = 32\n",
        "\n",
        "# Turn datasets into iterables (batches)\n",
        "train_dataloader = DataLoader(dataset=train_data,\n",
        "                              batch_size=BATCH_SIZE,\n",
        "                              shuffle=True)\n",
        "\n",
        "test_dataloader = DataLoader(dataset=test_data,\n",
        "                             batch_size=BATCH_SIZE,\n",
        "                             shuffle=False)\n",
        "\n",
        "train_dataloader, test_dataloader"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "6yqY_qwvz0Tx",
        "outputId": "088fd14d-dcdb-44c3-82ec-7abbc443f122"
      },
      "execution_count": 13,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(<torch.utils.data.dataloader.DataLoader at 0x7f8e42bb4fd0>,\n",
              " <torch.utils.data.dataloader.DataLoader at 0x7f8e42bb4150>)"
            ]
          },
          "metadata": {},
          "execution_count": 13
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Let's check out what what we've created\n",
        "print(f\"DataLoaders: {train_dataloader, test_dataloader}\")\n",
        "print(f\"Length of train_dataloader: {len(train_dataloader)} batches of {BATCH_SIZE}...\")\n",
        "print(f\"Length of test_dataloader: {len(test_dataloader)} batches of {BATCH_SIZE}...\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "qX99WZH5z0R2",
        "outputId": "f272010b-9ea3-4174-d165-d80c0eb922d8"
      },
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "DataLoaders: (<torch.utils.data.dataloader.DataLoader object at 0x7f8e42bb4fd0>, <torch.utils.data.dataloader.DataLoader object at 0x7f8e42bb4150>)\n",
            "Length of train_dataloader: 1875 batches of 32...\n",
            "Length of test_dataloader: 313 batches of 32...\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Check out what's inside the training dataloader\n",
        "train_features_batch, train_labels_batch = next(iter(train_dataloader))\n",
        "train_features_batch.shape, train_labels_batch.shape"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "OkJSLT8j3kNV",
        "outputId": "3f5adc11-fad3-48c0-e977-475e7fefef31"
      },
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(torch.Size([32, 1, 28, 28]), torch.Size([32]))"
            ]
          },
          "metadata": {},
          "execution_count": 15
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Show a sample\n",
        "# torch.manual_seed(42)\n",
        "random_idx = torch.randint(0, len(train_features_batch), size=[1]).item()\n",
        "img, label = train_features_batch[random_idx], train_labels_batch[random_idx]\n",
        "plt.imshow(img.squeeze(), cmap=\"gray\")\n",
        "plt.title(class_names[label])\n",
        "plt.axis(False)\n",
        "print(f\"Image size: {img.shape}\")\n",
        "print(f\"Label: {label}, label size: {label.shape}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 299
        },
        "id": "EJ0wvpH_z0PS",
        "outputId": "cd5a641d-a43e-4ba2-8158-8c9348fe71ac"
      },
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Image size: torch.Size([1, 28, 28])\n",
            "Label: 2, label size: torch.Size([])\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 3. Model 0: Build a basline model\n",
        "\n",
        "When starting to build a series of machine learning modelling experiments, it's best practice to start with a baseline model.\n",
        "\n",
        "A baseline model is a simple model you will try and improve upon with subsequent models/experiments.\n",
        "\n",
        "In other words: start simply and add complexity when necessary."
      ],
      "metadata": {
        "id": "mws9EhzVz0M6"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Create a flatten layer\n",
        "flatten_model = nn.Flatten() \n",
        "\n",
        "# Get a single sample\n",
        "x = train_features_batch[0]\n",
        "\n",
        "# Flatten the sample\n",
        "output = flatten_model(x) # perform forward pass\n",
        "\n",
        "# Print out what happened\n",
        "print(f\"Shape before flattening: {x.shape} -> [color_channels, height, width]\")\n",
        "print(f\"Shape after flattening: {output.shape} -> [color_channels, height*width]\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "oKobr0LNz0Kk",
        "outputId": "9dad6ab1-d396-4d7b-dc74-418aba15f9f9"
      },
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Shape before flattening: torch.Size([1, 28, 28]) -> [color_channels, height, width]\n",
            "Shape after flattening: torch.Size([1, 784]) -> [color_channels, height*width]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from torch import nn \n",
        "class FashionMNISTModelV0(nn.Module):\n",
        "  def __init__(self,\n",
        "               input_shape: int,\n",
        "               hidden_units: int,\n",
        "               output_shape: int):\n",
        "    super().__init__()\n",
        "    self.layer_stack = nn.Sequential(\n",
        "        nn.Flatten(),\n",
        "        nn.Linear(in_features=input_shape,\n",
        "                  out_features=hidden_units),\n",
        "        nn.Linear(in_features=hidden_units,\n",
        "                  out_features=output_shape)\n",
        "    )\n",
        "\n",
        "  def forward(self, x):\n",
        "    return self.layer_stack(x)"
      ],
      "metadata": {
        "id": "BMWS1CpgwM6e"
      },
      "execution_count": 18,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "torch.manual_seed(42)\n",
        "\n",
        "# Setup model with input parameters\n",
        "model_0 = FashionMNISTModelV0(\n",
        "    input_shape=28*28, # this is 28*28\n",
        "    hidden_units=10, # how mnay units in the hidden layer\n",
        "    output_shape=len(class_names) # one for every class\n",
        ").to(\"cpu\")\n",
        "\n",
        "model_0"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "wFWd8tKEwM4I",
        "outputId": "95e240a7-a834-455c-b114-4837ceb90851"
      },
      "execution_count": 19,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "FashionMNISTModelV0(\n",
              "  (layer_stack): Sequential(\n",
              "    (0): Flatten(start_dim=1, end_dim=-1)\n",
              "    (1): Linear(in_features=784, out_features=10, bias=True)\n",
              "    (2): Linear(in_features=10, out_features=10, bias=True)\n",
              "  )\n",
              ")"
            ]
          },
          "metadata": {},
          "execution_count": 19
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "dummy_x = torch.rand([1, 1, 28, 28])\n",
        "model_0(dummy_x)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "dHPmUY6D8NgB",
        "outputId": "063a0bd6-9886-484e-f629-5ce70d3a3de1"
      },
      "execution_count": 20,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[-0.0315,  0.3171,  0.0531, -0.2525,  0.5959,  0.2112,  0.3233,  0.2694,\n",
              "         -0.1004,  0.0157]], grad_fn=<AddmmBackward0>)"
            ]
          },
          "metadata": {},
          "execution_count": 20
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "model_0.state_dict()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "77n_DVy28Vi6",
        "outputId": "06f2b99b-2c74-4010-8ef0-b892b1851883"
      },
      "execution_count": 21,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "OrderedDict([('layer_stack.1.weight',\n",
              "              tensor([[ 0.0273,  0.0296, -0.0084,  ..., -0.0142,  0.0093,  0.0135],\n",
              "                      [-0.0188, -0.0354,  0.0187,  ..., -0.0106, -0.0001,  0.0115],\n",
              "                      [-0.0008,  0.0017,  0.0045,  ..., -0.0127, -0.0188,  0.0059],\n",
              "                      ...,\n",
              "                      [-0.0116,  0.0273, -0.0344,  ...,  0.0176,  0.0283, -0.0011],\n",
              "                      [-0.0230,  0.0257,  0.0291,  ..., -0.0187, -0.0087,  0.0001],\n",
              "                      [ 0.0176, -0.0147,  0.0053,  ..., -0.0336, -0.0221,  0.0205]])),\n",
              "             ('layer_stack.1.bias',\n",
              "              tensor([-0.0093,  0.0283, -0.0033,  0.0255,  0.0017,  0.0037, -0.0302, -0.0123,\n",
              "                       0.0018,  0.0163])),\n",
              "             ('layer_stack.2.weight',\n",
              "              tensor([[ 0.0614, -0.0687,  0.0021,  0.2718,  0.2109,  0.1079, -0.2279, -0.1063,\n",
              "                        0.2019,  0.2847],\n",
              "                      [-0.1495,  0.1344, -0.0740,  0.2006, -0.0475, -0.2514, -0.3130, -0.0118,\n",
              "                        0.0932, -0.1864],\n",
              "                      [ 0.2488,  0.1500,  0.1907,  0.1457, -0.3050, -0.0580,  0.1643,  0.1565,\n",
              "                       -0.2877, -0.1792],\n",
              "                      [ 0.2305, -0.2618,  0.2397, -0.0610,  0.0232,  0.1542,  0.0851, -0.2027,\n",
              "                        0.1030, -0.2715],\n",
              "                      [-0.1596, -0.0555, -0.0633,  0.2302, -0.1726,  0.2654,  0.1473,  0.1029,\n",
              "                        0.2252, -0.2160],\n",
              "                      [-0.2725,  0.0118,  0.1559,  0.1596,  0.0132,  0.3024,  0.1124,  0.1366,\n",
              "                       -0.1533,  0.0965],\n",
              "                      [-0.1184, -0.2555, -0.2057, -0.1909, -0.0477, -0.1324,  0.2905,  0.1307,\n",
              "                       -0.2629,  0.0133],\n",
              "                      [ 0.2727, -0.0127,  0.0513,  0.0863, -0.1043, -0.2047, -0.1185, -0.0825,\n",
              "                        0.2488, -0.2571],\n",
              "                      [ 0.0425, -0.1209, -0.0336, -0.0281, -0.1227,  0.0730,  0.0747, -0.1816,\n",
              "                        0.1943,  0.2853],\n",
              "                      [-0.1310,  0.0645, -0.1171,  0.2168, -0.0245, -0.2820,  0.0736,  0.2621,\n",
              "                        0.0012, -0.0810]])),\n",
              "             ('layer_stack.2.bias',\n",
              "              tensor([-0.0087,  0.1791,  0.2712, -0.0791,  0.1685,  0.1762,  0.2825,  0.2266,\n",
              "                      -0.2612, -0.2613]))])"
            ]
          },
          "metadata": {},
          "execution_count": 21
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 3.1 Setup loss, optimizer and evaluation metrics\n",
        "\n",
        "* Loss function - since we're working with multi-class data, our loss function will be `nn.CrossEntropyLoss()`\n",
        "* Optimizer - our optimizer `torch.optim.SGD()` (stochastic gradient descent)\n",
        "* Evaluation metric - since we're working on a classification problem, let's use accruacy as our evaluation metric"
      ],
      "metadata": {
        "id": "3lpa6M-TCwvm"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import requests\n",
        "from pathlib import Path\n",
        "\n",
        "# Download helper functions from Learn PyTorch repo\n",
        "if Path(\"helper_functions.py\").is_file():\n",
        "  print(\"helper_functions.py already exists, skipping download...\")\n",
        "else:\n",
        "  print(\"Downloading helper_functions.py\")\n",
        "  request = requests.get(\"https://raw.githubusercontent.com/mrdbourke/pytorch-deep-learning/main/helper_functions.py\")\n",
        "  with open(\"helper_functions.py\", \"wb\") as f:\n",
        "    f.write(request.content)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "0oJnaykIDQ4h",
        "outputId": "f9770a54-f442-444c-f79c-a1815abfa71c"
      },
      "execution_count": 22,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "helper_functions.py already exists, skipping download...\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Import accuracy metric\n",
        "from helper_functions import accuracy_fn\n",
        "\n",
        "# Setup loss function and optimizer\n",
        "loss_fn = nn.CrossEntropyLoss()\n",
        "optimizer = torch.optim.SGD(params=model_0.parameters(),\n",
        "                            lr=0.1)"
      ],
      "metadata": {
        "id": "__X-9FfGDQva"
      },
      "execution_count": 23,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 3.2 Creating a function to time our experiments\n",
        "\n",
        "Machine learning is very experimental.\n",
        "\n",
        "Two of the main things you'll often want to track are:\n",
        "1. Model's performance (loss and accuracy values etc)\n",
        "2. How fast it runs "
      ],
      "metadata": {
        "id": "vQciMkdIFADj"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from timeit import default_timer as timer \n",
        "def print_train_time(start: float,\n",
        "                     end: float, \n",
        "                     device: torch.device = None):\n",
        "  \"\"\"Prints difference between start and end time.\"\"\"\n",
        "  total_time = end - start\n",
        "  print(f\"Train time on {device}: {total_time:.3f} seconds\")\n",
        "  return total_time"
      ],
      "metadata": {
        "id": "EFlhet9sFXms"
      },
      "execution_count": 24,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "start_time = timer()\n",
        "# some code...\n",
        "end_time = timer()\n",
        "print_train_time(start=start_time, end=end_time, device=\"cpu\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "OmLoTJXFGLOC",
        "outputId": "16d70985-0d96-481d-8d81-973c755d2f44"
      },
      "execution_count": 25,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Train time on cpu: 0.000 seconds\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "2.397800017206464e-05"
            ]
          },
          "metadata": {},
          "execution_count": 25
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 3.3 Creating a training loop and training a model on batches of data\n",
        "\n",
        "1. Loop through epochs.\n",
        "2. Loop through training batches, perform training steps, calculate the train loss *per batch*.\n",
        "3. Loop through testing batches, perform testing steps, calculate the test loss *per batch*.\n",
        "4. Print out what's happening.\n",
        "5. Time it all (for fun).\n",
        "\n",
        "**Note:** Because we are computing on *batches*, the optimizer will update the model's parameters once *per batch* rather than once per epoch."
      ],
      "metadata": {
        "id": "pKphbOeob589"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Import tqdm for progress bar\n",
        "from tqdm.auto import tqdm\n",
        "\n",
        "# Set the seed and start the timer\n",
        "torch.manual_seed(42)\n",
        "train_time_start_on_cpu = timer() \n",
        "\n",
        "# Set the number of epochs (we'll keep this small for faster training time)\n",
        "epochs = 3\n",
        "\n",
        "# Create training and test loop\n",
        "for epoch in tqdm(range(epochs)):\n",
        "  print(f\"Epoch: {epoch}\\n------\")\n",
        "  ### Training\n",
        "  train_loss = 0\n",
        "  # Add a loop to loop through the training batches\n",
        "  for batch, (X, y) in enumerate(train_dataloader):\n",
        "    model_0.train()\n",
        "    # 1. Forward pass\n",
        "    y_pred = model_0(X)\n",
        "    \n",
        "    # 2. Calculate loss (per batch)\n",
        "    loss = loss_fn(y_pred, y)\n",
        "    train_loss += loss # accumulate train loss\n",
        "    \n",
        "    # 3. Optimizer zero grad\n",
        "    optimizer.zero_grad()\n",
        "    \n",
        "    # 4. Loss backward\n",
        "    loss.backward()\n",
        "    \n",
        "    # 5. Optimizer step (update the model's parameters once *per batch*)\n",
        "    optimizer.step()\n",
        "    \n",
        "    # Print out what's happening\n",
        "    if batch % 400 == 0:\n",
        "        print(f\"Looked at {batch * len(X)}/{len(train_dataloader.dataset)} samples.\")\n",
        "  \n",
        "  # Divide total train loss by length of train dataloader\n",
        "  train_loss /= len(train_dataloader)\n",
        "\n",
        "  ### Testing\n",
        "  test_loss, test_acc = 0, 0\n",
        "  model_0.eval()\n",
        "  with torch.inference_mode(): \n",
        "    for X_test, y_test in test_dataloader:\n",
        "      # 1. Forward pass\n",
        "      test_pred = model_0(X_test)\n",
        "\n",
        "      # 2. Calculate loss (accumulatively)\n",
        "      test_loss += loss_fn(test_pred, y_test)\n",
        "\n",
        "      # 3. Calculate accuracy\n",
        "      test_acc += accuracy_fn(y_true=y_test, y_pred=test_pred.argmax(dim=1))\n",
        "\n",
        "    # Calculate the test loss average per batch\n",
        "    test_loss /= len(test_dataloader)\n",
        "\n",
        "    # Calculate the test acc average per batch\n",
        "    test_acc /= len(test_dataloader)\n",
        "\n",
        "  # Print out what's happening\n",
        "  print(f\"\\nTrain loss: {train_loss:.4f} | Test loss: {test_loss:.4f}, Test acc: {test_acc:.4f}\")\n",
        "\n",
        "# Calculate training time\n",
        "train_time_end_on_cpu = timer()\n",
        "total_train_time_model_0 = print_train_time(start=train_time_start_on_cpu,\n",
        "                                            end=train_time_end_on_cpu,\n",
        "                                            device=str(next(model_0.parameters()).device))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 546,
          "referenced_widgets": [
            "452c6620083e4fe79ad988c4e03bae92",
            "2ba9710ece4447cc85a60ac113d625a7",
            "ac67fff509494ef89bf39def872f75c5",
            "d9918747d9e84891803b9f7bcc2c0c46",
            "56c6bd1514e543c1a6a84b1d78b9ed05",
            "c052fb7f36ce4e1a986966a843d6bfd6",
            "b37bb81ea00147a88e6b583c0cb5d3c3",
            "50361c8ffd78409a91a4a6a2b2469f78",
            "f354b5dc96384b2aa2e975a84a5d8be3",
            "303cfad4137145a5aee3714b965e89ab",
            "15da326bed9443c390f550c3e395d62a"
          ]
        },
        "id": "pznzwwX8b9Gr",
        "outputId": "9a38dd0f-829a-4cac-9d61-7d522c6e4adf"
      },
      "execution_count": 26,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "  0%|          | 0/3 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "452c6620083e4fe79ad988c4e03bae92"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Epoch: 0\n",
            "------\n",
            "Looked at 0/60000 samples.\n",
            "Looked at 12800/60000 samples.\n",
            "Looked at 25600/60000 samples.\n",
            "Looked at 38400/60000 samples.\n",
            "Looked at 51200/60000 samples.\n",
            "\n",
            "Train loss: 0.5904 | Test loss: 0.5095, Test acc: 82.0387\n",
            "Epoch: 1\n",
            "------\n",
            "Looked at 0/60000 samples.\n",
            "Looked at 12800/60000 samples.\n",
            "Looked at 25600/60000 samples.\n",
            "Looked at 38400/60000 samples.\n",
            "Looked at 51200/60000 samples.\n",
            "\n",
            "Train loss: 0.4763 | Test loss: 0.4799, Test acc: 83.1969\n",
            "Epoch: 2\n",
            "------\n",
            "Looked at 0/60000 samples.\n",
            "Looked at 12800/60000 samples.\n",
            "Looked at 25600/60000 samples.\n",
            "Looked at 38400/60000 samples.\n",
            "Looked at 51200/60000 samples.\n",
            "\n",
            "Train loss: 0.4550 | Test loss: 0.4766, Test acc: 83.4265\n",
            "Train time on cpu: 26.749 seconds\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 4. Make predictions and get Model 0 results"
      ],
      "metadata": {
        "id": "dnrsjPj_gYna"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "torch.manual_seed(42)\n",
        "def eval_model(model: torch.nn.Module,\n",
        "               data_loader: torch.utils.data.DataLoader,\n",
        "               loss_fn: torch.nn.Module, \n",
        "               accuracy_fn):\n",
        "  \"\"\"Returns a dictionary containing the results of model predicting on data_loader.\"\"\"\n",
        "  loss, acc = 0, 0\n",
        "  model.eval()\n",
        "  with torch.inference_mode():\n",
        "    for X, y in tqdm(data_loader):\n",
        "      # Make predictions\n",
        "      y_pred = model(X)\n",
        "\n",
        "      # Accumulate the loss and acc values per batch\n",
        "      loss += loss_fn(y_pred, y)\n",
        "      acc += accuracy_fn(y_true=y,\n",
        "                         y_pred=y_pred.argmax(dim=1))\n",
        "\n",
        "    # Scale loss and acc to find the average loss/acc per batch\n",
        "    loss /= len(data_loader)\n",
        "    acc /= len(data_loader)\n",
        "\n",
        "  return {\"model_name\": model.__class__.__name__, # only works when model was created with a class\n",
        "          \"model_loss\": loss.item(),\n",
        "          \"model_acc\": acc}\n",
        "\n",
        "# Calculate model 0 results on test dataset\n",
        "model_0_results = eval_model(model=model_0,\n",
        "                             data_loader=test_dataloader,\n",
        "                             loss_fn=loss_fn, \n",
        "                             accuracy_fn=accuracy_fn)\n",
        "model_0_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 102,
          "referenced_widgets": [
            "eab7f3156614459ea1fa8a15e32e3873",
            "fc81120620dc4407b45aabd76ee21b52",
            "3e8afe57ca034e2e85f90e991334ec4d",
            "d89786d655c048dfa5997ce10e71eb88",
            "c84e5af5da0841d6b16131e737f7ae04",
            "35cc83324da54f67b81bc99682cd0b66",
            "5ee12da0478748518b500de506bf1130",
            "170eb1aac72c4d66ad647f4ba8381d71",
            "4496b5cf6c1f40b4a50a0a130e2dc4ac",
            "6a22d5e2a68d43e0ba29db7e0287a2ce",
            "b547009c04b2437d9b70629476be5c60"
          ]
        },
        "id": "jvljaEB3geiC",
        "outputId": "cc8bf3aa-c0af-42d8-c974-3404713cc751"
      },
      "execution_count": 27,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "  0%|          | 0/313 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "eab7f3156614459ea1fa8a15e32e3873"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'model_acc': 83.42651757188499,\n",
              " 'model_loss': 0.47663888335227966,\n",
              " 'model_name': 'FashionMNISTModelV0'}"
            ]
          },
          "metadata": {},
          "execution_count": 27
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 5. Setup device agnostic-code (for using a GPU if there is one)\n",
        "\n",
        "\n"
      ],
      "metadata": {
        "id": "0wQk04h9jsrJ"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!nvidia-smi"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Ge8vE0gUkOu0",
        "outputId": "3e45853b-12a3-4871-a39a-ee44d94901be"
      },
      "execution_count": 28,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Sat Apr 23 01:36:35 2022       \n",
            "+-----------------------------------------------------------------------------+\n",
            "| NVIDIA-SMI 460.32.03    Driver Version: 460.32.03    CUDA Version: 11.2     |\n",
            "|-------------------------------+----------------------+----------------------+\n",
            "| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |\n",
            "| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |\n",
            "|                               |                      |               MIG M. |\n",
            "|===============================+======================+======================|\n",
            "|   0  Tesla P100-PCIE...  Off  | 00000000:00:04.0 Off |                    0 |\n",
            "| N/A   37C    P0    29W / 250W |      2MiB / 16280MiB |      0%      Default |\n",
            "|                               |                      |                  N/A |\n",
            "+-------------------------------+----------------------+----------------------+\n",
            "                                                                               \n",
            "+-----------------------------------------------------------------------------+\n",
            "| Processes:                                                                  |\n",
            "|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |\n",
            "|        ID   ID                                                   Usage      |\n",
            "|=============================================================================|\n",
            "|  No running processes found                                                 |\n",
            "+-----------------------------------------------------------------------------+\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "torch.cuda.is_available()"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "XVRY_vSCkh3o",
        "outputId": "0733c7c0-f910-46cd-9166-1ef618977e2f"
      },
      "execution_count": 29,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "metadata": {},
          "execution_count": 29
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Setup device-agnostic code\n",
        "import torch \n",
        "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
        "device"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "id": "LlGfiRYtklAF",
        "outputId": "d92ce2b6-cf11-4113-9101-5fdc267c61b3"
      },
      "execution_count": 30,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "'cuda'"
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 30
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 6. Model 1: Building a better model with non-linearity \n",
        "\n",
        "We learned about the power of non-linearity in notebook 02 - https://www.learnpytorch.io/02_pytorch_classification/#6-the-missing-piece-non-linearity"
      ],
      "metadata": {
        "id": "UB4nyeJwlGZ_"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Create a model with non-linear and linear layers\n",
        "class FashionMNISTModelV1(nn.Module):\n",
        "  def __init__(self,\n",
        "               input_shape: int,\n",
        "               hidden_units: int,\n",
        "               output_shape: int):\n",
        "    super().__init__()\n",
        "    self.layer_stack = nn.Sequential(\n",
        "        nn.Flatten(), # flatten inputs into a single vector\n",
        "        nn.Linear(in_features=input_shape,\n",
        "                  out_features=hidden_units),\n",
        "        nn.ReLU(),\n",
        "        nn.Linear(in_features=hidden_units,\n",
        "                  out_features=output_shape),\n",
        "        nn.ReLU()\n",
        "    )\n",
        "  \n",
        "  def forward(self, x: torch.Tensor):\n",
        "    return self.layer_stack(x)"
      ],
      "metadata": {
        "id": "bbAcCd6AIuik"
      },
      "execution_count": 31,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Create an instance of model_1\n",
        "torch.manual_seed(42)\n",
        "model_1 = FashionMNISTModelV1(input_shape=784, # this is the output of the flatten after our 28*28 image goes in\n",
        "                              hidden_units=10,\n",
        "                              output_shape=len(class_names)).to(device) # send to the GPU if it's available\n",
        "next(model_1.parameters()).device"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "uTXVra4QJX6a",
        "outputId": "29683c57-8c90-4e5c-ab52-aface2120fa1"
      },
      "execution_count": 32,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "device(type='cuda', index=0)"
            ]
          },
          "metadata": {},
          "execution_count": 32
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 6.1 Setup loss, optimizer and evaluation metrics"
      ],
      "metadata": {
        "id": "c3ldnyWxJX0D"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from helper_functions import accuracy_fn\n",
        "loss_fn = nn.CrossEntropyLoss() # measure how wrong our model is\n",
        "optimizer = torch.optim.SGD(params=model_1.parameters(), # tries to update our model's parameters to reduce the loss \n",
        "                            lr=0.1)"
      ],
      "metadata": {
        "id": "mSdP9w4FJXuc"
      },
      "execution_count": 33,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 6.2 Functionizing training and evaluation/testing loops \n",
        "\n",
        "Let's create a function for:\n",
        "* training loop - `train_step()`\n",
        "* testing loop - `test_step()`"
      ],
      "metadata": {
        "id": "EgyjcJNVJXf3"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "def train_step(model: torch.nn.Module,\n",
        "               data_loader: torch.utils.data.DataLoader,\n",
        "               loss_fn: torch.nn.Module,\n",
        "               optimizer: torch.optim.Optimizer,\n",
        "               accuracy_fn,\n",
        "               device: torch.device = device):\n",
        "  \"\"\"Performs a training with model trying to learn on data_loader.\"\"\"\n",
        "  train_loss, train_acc = 0, 0\n",
        "\n",
        "  # Put model into training mode\n",
        "  model.train()\n",
        "\n",
        "  # Add a loop to loop through the training batches\n",
        "  for batch, (X, y) in enumerate(data_loader):\n",
        "    # Put data on target device \n",
        "    X, y = X.to(device), y.to(device)\n",
        "\n",
        "    # 1. Forward pass (outputs the raw logits from the model)\n",
        "    y_pred = model(X)\n",
        "    \n",
        "    # 2. Calculate loss and accuracy (per batch)\n",
        "    loss = loss_fn(y_pred, y)\n",
        "    train_loss += loss # accumulate train loss\n",
        "    train_acc += accuracy_fn(y_true=y,\n",
        "                             y_pred=y_pred.argmax(dim=1)) # go from logits -> prediction labels\n",
        "    \n",
        "    # 3. Optimizer zero grad\n",
        "    optimizer.zero_grad()\n",
        "    \n",
        "    # 4. Loss backward\n",
        "    loss.backward()\n",
        "    \n",
        "    # 5. Optimizer step (update the model's parameters once *per batch*)\n",
        "    optimizer.step()\n",
        "  \n",
        "  # Divide total train loss and acc by length of train dataloader\n",
        "  train_loss /= len(data_loader)\n",
        "  train_acc /= len(data_loader)\n",
        "  print(f\"Train loss: {train_loss:.5f} | Train acc: {train_acc:.2f}%\")"
      ],
      "metadata": {
        "id": "8S4mmNrzL3AO"
      },
      "execution_count": 34,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "def test_step(model: torch.nn.Module,\n",
        "              data_loader: torch.utils.data.DataLoader, \n",
        "              loss_fn: torch.nn.Module,\n",
        "              accuracy_fn,\n",
        "              device: torch.device = device):\n",
        "  \"\"\"Performs a testing loop step on model going over data_loader.\"\"\"\n",
        "  test_loss, test_acc = 0, 0\n",
        "  \n",
        "  # Put the model in eval mode\n",
        "  model.eval()\n",
        "\n",
        "  # Turn on inference mode context manager\n",
        "  with torch.inference_mode():\n",
        "    for X, y in data_loader:\n",
        "      # Send the data to the target device\n",
        "      X, y = X.to(device), y.to(device)\n",
        "\n",
        "      # 1. Forward pass (outputs raw logits)\n",
        "      test_pred = model(X)\n",
        "\n",
        "      # 2. Calculuate the loss/acc\n",
        "      test_loss += loss_fn(test_pred, y)\n",
        "      test_acc += accuracy_fn(y_true=y,\n",
        "                              y_pred=test_pred.argmax(dim=1)) # go from logits -> prediction labels \n",
        "\n",
        "    # Adjust metrics and print out\n",
        "    test_loss /= len(data_loader)\n",
        "    test_acc /= len(data_loader)\n",
        "    print(f\"Test loss: {test_loss:.5f} | Test acc: {test_acc:.2f}%\\n\")"
      ],
      "metadata": {
        "id": "g-QooNdIQXKO"
      },
      "execution_count": 35,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "torch.manual_seed(42)\n",
        "\n",
        "# Measure time\n",
        "from timeit import default_timer as timer\n",
        "train_time_start_on_gpu = timer()\n",
        "\n",
        "# Set epochs\n",
        "epochs = 3\n",
        "\n",
        "# Create a optimization and evaluation loop using train_step() and test_step()\n",
        "for epoch in tqdm(range(epochs)):\n",
        "  print(f\"Epoch: {epoch}\\n----------\")\n",
        "  train_step(model=model_1,\n",
        "             data_loader=train_dataloader,\n",
        "             loss_fn=loss_fn,\n",
        "             optimizer=optimizer,\n",
        "             accuracy_fn=accuracy_fn,\n",
        "             device=device)\n",
        "  test_step(model=model_1,\n",
        "            data_loader=test_dataloader,\n",
        "            loss_fn=loss_fn,\n",
        "            accuracy_fn=accuracy_fn,\n",
        "            device=device)\n",
        "\n",
        "train_time_end_on_gpu = timer()\n",
        "total_train_time_model_1 = print_train_time(start=train_time_start_on_gpu,\n",
        "                                            end=train_time_end_on_gpu,\n",
        "                                            device=device)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 333,
          "referenced_widgets": [
            "7fa9e645d1224e20848095ac475b7fb9",
            "f3b285dce5944552b7086aab6a3f5173",
            "a3c43e08bc234328a01dfd3c2c39435a",
            "910d36919e354b26aa96653469a74593",
            "63934d0b6964446ebc25bb87e0cf14d0",
            "2dfe739f14a843d69ffa569c7ba88065",
            "63ededa6c647434a839fa235e85ca219",
            "0ddf644c4c5f40bb8131f2182ec9c95c",
            "f01cb38994b74f73a198b166b62562b4",
            "f92ad21514a746eba2d1670ba6558972",
            "91e00967267042968c70a214439ef67a"
          ]
        },
        "id": "9Yxs67miRnVk",
        "outputId": "5a86389d-f78f-4afe-ce2c-a8640ec4be53"
      },
      "execution_count": 36,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "  0%|          | 0/3 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "7fa9e645d1224e20848095ac475b7fb9"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Epoch: 0\n",
            "----------\n",
            "Train loss: 1.09199 | Train acc: 61.34%\n",
            "Test loss: 0.95636 | Test acc: 65.00%\n",
            "\n",
            "Epoch: 1\n",
            "----------\n",
            "Train loss: 0.78101 | Train acc: 71.93%\n",
            "Test loss: 0.72227 | Test acc: 73.91%\n",
            "\n",
            "Epoch: 2\n",
            "----------\n",
            "Train loss: 0.67027 | Train acc: 75.94%\n",
            "Test loss: 0.68500 | Test acc: 75.02%\n",
            "\n",
            "Train time on cuda: 20.042 seconds\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "> **Note:** Sometimes, depending on your data/hardware you might find that your model trains faster on CPU than GPU.\n",
        "> \n",
        "> Why is this?\n",
        ">\n",
        "> 1. It could be that the overhead for copying data/model to and from the GPU outweighs the compute benefits offered by the GPU.\n",
        "> 2. The hardware you're using has a better CPU in terms compute capability than the GPU.\n",
        ">\n",
        "> For more on how to make your models compute faster, see here: https://horace.io/brrr_intro.html"
      ],
      "metadata": {
        "id": "KpMNG0xfUUBp"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "model_0_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "vETRyC9ySpcr",
        "outputId": "72273a9a-e700-42b7-b237-c8abe802253c"
      },
      "execution_count": 37,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'model_acc': 83.42651757188499,\n",
              " 'model_loss': 0.47663888335227966,\n",
              " 'model_name': 'FashionMNISTModelV0'}"
            ]
          },
          "metadata": {},
          "execution_count": 37
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Train time on CPU\n",
        "total_train_time_model_0"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Rxq5Mm-USpVd",
        "outputId": "4c2ca45a-f49e-40db-fff3-7544695ef76f"
      },
      "execution_count": 38,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "26.74877341499996"
            ]
          },
          "metadata": {},
          "execution_count": 38
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Get model_1 results dictionary\n",
        "model_1_results = eval_model(model=model_1,\n",
        "                             data_loader=test_dataloader,\n",
        "                             loss_fn=loss_fn,\n",
        "                             accuracy_fn=accuracy_fn)\n",
        "model_1_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 419,
          "referenced_widgets": [
            "3a596cf0f9404d82ad70e8b9f4b1e7ee",
            "ba7a0a1af903433a82d884f2d94dc02e",
            "02acd0d634fc4c3aab9ae53d25cc7f6a",
            "cef3ab0d6ff4475aaf7248e213c1eb5b",
            "26c959ed124f4586b440323ef07ef3e9",
            "106cce0a1b674d21aee8b4c95ae53fc1",
            "2c43121dfcca4cd6a88770d7f4e19869",
            "a46acba8f3664e10a6c58f5114ff92ec",
            "03cde3f254604b37a8316e7fb909c986",
            "7df2b9c9f4314518b6e14c89add6bb6d",
            "5cc320c63cf442c997c6c2f34fbb80f4"
          ]
        },
        "id": "LwQ-M7P0T-8i",
        "outputId": "7a8e1e02-2276-441b-a346-fa695c98e4ae"
      },
      "execution_count": 39,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "  0%|          | 0/313 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "3a596cf0f9404d82ad70e8b9f4b1e7ee"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "error",
          "ename": "RuntimeError",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-39-801e93364267>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      3\u001b[0m                              \u001b[0mdata_loader\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtest_dataloader\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m                              \u001b[0mloss_fn\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mloss_fn\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m                              accuracy_fn=accuracy_fn)\n\u001b[0m\u001b[1;32m      6\u001b[0m \u001b[0mmodel_1_results\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m<ipython-input-27-c5b127dad9f6>\u001b[0m in \u001b[0;36meval_model\u001b[0;34m(model, data_loader, loss_fn, accuracy_fn)\u001b[0m\n\u001b[1;32m     10\u001b[0m     \u001b[0;32mfor\u001b[0m \u001b[0mX\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtqdm\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata_loader\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m       \u001b[0;31m# Make predictions\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 12\u001b[0;31m       \u001b[0my_pred\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mX\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     13\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     14\u001b[0m       \u001b[0;31m# Accumulate the loss and acc values per batch\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py\u001b[0m in \u001b[0;36m_call_impl\u001b[0;34m(self, *input, **kwargs)\u001b[0m\n\u001b[1;32m   1100\u001b[0m         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks\n\u001b[1;32m   1101\u001b[0m                 or _global_forward_hooks or _global_forward_pre_hooks):\n\u001b[0;32m-> 1102\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mforward_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1103\u001b[0m         \u001b[0;31m# Do not call functions when jit is used\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1104\u001b[0m         \u001b[0mfull_backward_hooks\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnon_full_backward_hooks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m<ipython-input-31-2284727bcc95>\u001b[0m in \u001b[0;36mforward\u001b[0;34m(self, x)\u001b[0m\n\u001b[1;32m     17\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     18\u001b[0m   \u001b[0;32mdef\u001b[0m \u001b[0mforward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTensor\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 19\u001b[0;31m     \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlayer_stack\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py\u001b[0m in \u001b[0;36m_call_impl\u001b[0;34m(self, *input, **kwargs)\u001b[0m\n\u001b[1;32m   1100\u001b[0m         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks\n\u001b[1;32m   1101\u001b[0m                 or _global_forward_hooks or _global_forward_pre_hooks):\n\u001b[0;32m-> 1102\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mforward_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1103\u001b[0m         \u001b[0;31m# Do not call functions when jit is used\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1104\u001b[0m         \u001b[0mfull_backward_hooks\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnon_full_backward_hooks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/torch/nn/modules/container.py\u001b[0m in \u001b[0;36mforward\u001b[0;34m(self, input)\u001b[0m\n\u001b[1;32m    139\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mforward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minput\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    140\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0mmodule\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 141\u001b[0;31m             \u001b[0minput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodule\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    142\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0minput\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    143\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/torch/nn/modules/module.py\u001b[0m in \u001b[0;36m_call_impl\u001b[0;34m(self, *input, **kwargs)\u001b[0m\n\u001b[1;32m   1100\u001b[0m         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks\n\u001b[1;32m   1101\u001b[0m                 or _global_forward_hooks or _global_forward_pre_hooks):\n\u001b[0;32m-> 1102\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mforward_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1103\u001b[0m         \u001b[0;31m# Do not call functions when jit is used\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1104\u001b[0m         \u001b[0mfull_backward_hooks\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnon_full_backward_hooks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/torch/nn/modules/linear.py\u001b[0m in \u001b[0;36mforward\u001b[0;34m(self, input)\u001b[0m\n\u001b[1;32m    101\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    102\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mforward\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minput\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mTensor\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m->\u001b[0m \u001b[0mTensor\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 103\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0mF\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinear\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mweight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    104\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    105\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mextra_repr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m->\u001b[0m \u001b[0mstr\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/torch/nn/functional.py\u001b[0m in \u001b[0;36mlinear\u001b[0;34m(input, weight, bias)\u001b[0m\n\u001b[1;32m   1846\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mhas_torch_function_variadic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mweight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1847\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mhandle_torch_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlinear\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mweight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mweight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1848\u001b[0;31m     \u001b[0;32mreturn\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_C\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_nn\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinear\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mweight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1849\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1850\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;31mRuntimeError\u001b[0m: Expected all tensors to be on the same device, but found at least two devices, cuda:0 and cpu! (when checking argument for argument mat1 in method wrapper_addmm)"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "torch.manual_seed(42)\n",
        "def eval_model(model: torch.nn.Module,\n",
        "               data_loader: torch.utils.data.DataLoader,\n",
        "               loss_fn: torch.nn.Module, \n",
        "               accuracy_fn,\n",
        "               device=device):\n",
        "  \"\"\"Returns a dictionary containing the results of model predicting on data_loader.\"\"\"\n",
        "  loss, acc = 0, 0\n",
        "  model.eval()\n",
        "  with torch.inference_mode():\n",
        "    for X, y in tqdm(data_loader):\n",
        "      # Make our data device agnostic\n",
        "      X, y = X.to(device), y.to(device)\n",
        "      # Make predictions\n",
        "      y_pred = model(X)\n",
        "\n",
        "      # Accumulate the loss and acc values per batch\n",
        "      loss += loss_fn(y_pred, y)\n",
        "      acc += accuracy_fn(y_true=y,\n",
        "                         y_pred=y_pred.argmax(dim=1))\n",
        "\n",
        "    # Scale loss and acc to find the average loss/acc per batch\n",
        "    loss /= len(data_loader)\n",
        "    acc /= len(data_loader)\n",
        "\n",
        "  return {\"model_name\": model.__class__.__name__, # only works when model was created with a class\n",
        "          \"model_loss\": loss.item(),\n",
        "          \"model_acc\": acc}"
      ],
      "metadata": {
        "id": "oJDpTeuzarWw"
      },
      "execution_count": 40,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Get model_1 results dictionary\n",
        "model_1_results = eval_model(model=model_1,\n",
        "                             data_loader=test_dataloader,\n",
        "                             loss_fn=loss_fn,\n",
        "                             accuracy_fn=accuracy_fn,\n",
        "                             device=device)\n",
        "model_1_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 102,
          "referenced_widgets": [
            "86b6aa2170e5416785241eb54d312b24",
            "d5f08fedd2084a46a6127d19ec60c8d7",
            "18886c8d03ab4b908554b8e4ede69975",
            "0fd4cfa3085c4cf6b7bd73b8fb956e63",
            "aa8f9267d9a849fabb001a9b9fdae854",
            "bde0302d529d42b388cc14b76eb8997b",
            "04434f22ab084e2aa4291eb76dd8caec",
            "bbeeb4d3f59b48ac9443d29200de1868",
            "7ca50270baed4c069bec8e49f68437ef",
            "deec91f27061464995ea185dac966197",
            "31e634fc47d5405a9751588e659db601"
          ]
        },
        "id": "Mnaruh1-bIad",
        "outputId": "ea71b04c-55d6-4cae-e408-f40a0e1e1084"
      },
      "execution_count": 41,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "  0%|          | 0/313 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "86b6aa2170e5416785241eb54d312b24"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'model_acc': 75.01996805111821,\n",
              " 'model_loss': 0.6850008368492126,\n",
              " 'model_name': 'FashionMNISTModelV1'}"
            ]
          },
          "metadata": {},
          "execution_count": 41
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "model_0_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "YHlIT6QbbPTm",
        "outputId": "049cd865-fbe8-4813-ec8f-dc662f313db3"
      },
      "execution_count": 42,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'model_acc': 83.42651757188499,\n",
              " 'model_loss': 0.47663888335227966,\n",
              " 'model_name': 'FashionMNISTModelV0'}"
            ]
          },
          "metadata": {},
          "execution_count": 42
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Model 2: Building a Convolutional Neural Network (CNN)\n",
        "\n",
        "CNN's are also known ConvNets.\n",
        "\n",
        "CNN's are known for their capabilities to find patterns in visual data.\n",
        "\n",
        "To find out what's happening inside a CNN, see this website: https://poloclub.github.io/cnn-explainer/"
      ],
      "metadata": {
        "id": "anIzg6CfcDen"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Create a convolutional neural network\n",
        "class FashionMNISTModelV2(nn.Module):\n",
        "  \"\"\"\n",
        "  Model architecture that replicates the TinyVGG\n",
        "  model from CNN explainer website.\n",
        "  \"\"\"\n",
        "  def __init__(self, input_shape: int, hidden_units: int, output_shape: int):\n",
        "    super().__init__()\n",
        "    self.conv_block_1 = nn.Sequential(\n",
        "        # Create a conv layer - https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html\n",
        "        nn.Conv2d(in_channels=input_shape, \n",
        "                  out_channels=hidden_units,\n",
        "                  kernel_size=3,\n",
        "                  stride=1,\n",
        "                  padding=1), # values we can set ourselves in our NN's are called hyperparameters\n",
        "        nn.ReLU(),\n",
        "        nn.Conv2d(in_channels=hidden_units,\n",
        "                  out_channels=hidden_units,\n",
        "                  kernel_size=3,\n",
        "                  stride=1,\n",
        "                  padding=1),\n",
        "        nn.ReLU(),\n",
        "        nn.MaxPool2d(kernel_size=2)\n",
        "    )\n",
        "    self.conv_block_2 = nn.Sequential(\n",
        "        nn.Conv2d(in_channels=hidden_units,\n",
        "                  out_channels=hidden_units,\n",
        "                  kernel_size=3,\n",
        "                  stride=1,\n",
        "                  padding=1),\n",
        "        nn.ReLU(),\n",
        "        nn.Conv2d(in_channels=hidden_units,\n",
        "                  out_channels=hidden_units,\n",
        "                  kernel_size=3,\n",
        "                  stride=1,\n",
        "                  padding=1),\n",
        "        nn.ReLU(),\n",
        "        nn.MaxPool2d(kernel_size=2)\n",
        "    )\n",
        "    self.classifier = nn.Sequential(\n",
        "        nn.Flatten(),\n",
        "        nn.Linear(in_features=hidden_units*7*7, # there's a trick to calculating this...\n",
        "                  out_features=output_shape)\n",
        "    )\n",
        "\n",
        "  def forward(self, x):\n",
        "    x = self.conv_block_1(x)\n",
        "    # print(f\"Output shape of conv_block_1: {x.shape}\")\n",
        "    x = self.conv_block_2(x) \n",
        "    # print(f\"Output shape of conv_block_2: {x.shape}\")\n",
        "    x = self.classifier(x)\n",
        "    # print(f\"Output shape of classifier: {x.shape}\")\n",
        "    return x"
      ],
      "metadata": {
        "id": "qtuAmB5rcZpq"
      },
      "execution_count": 43,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "torch.manual_seed(42)\n",
        "model_2 = FashionMNISTModelV2(input_shape=1,\n",
        "                              hidden_units=10,\n",
        "                              output_shape=len(class_names)).to(device)"
      ],
      "metadata": {
        "id": "L9vvROr-h-Hc"
      },
      "execution_count": 44,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "rand_image_tensor = torch.randn(size=(1, 28, 28))\n",
        "rand_image_tensor.shape"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "myaqpXZOKUp4",
        "outputId": "917dabb9-7eaa-496a-96ca-c68de90462e5"
      },
      "execution_count": 45,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([1, 28, 28])"
            ]
          },
          "metadata": {},
          "execution_count": 45
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Pass image through model\n",
        "model_2(rand_image_tensor.unsqueeze(0).to(device))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "pmQpOkq9KPks",
        "outputId": "d53b7d53-16db-42d1-c8f7-7179e723e237"
      },
      "execution_count": 46,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[ 0.0366, -0.0940,  0.0686, -0.0485,  0.0068,  0.0290,  0.0132,  0.0084,\n",
              "         -0.0030, -0.0185]], device='cuda:0', grad_fn=<AddmmBackward0>)"
            ]
          },
          "metadata": {},
          "execution_count": 46
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "plt.imshow(image.squeeze(), cmap=\"gray\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 283
        },
        "id": "eqo8TZ6nKCXW",
        "outputId": "d8050f8e-be3b-44ae-ff40-a81bff3e8432"
      },
      "execution_count": 47,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.image.AxesImage at 0x7f8e43543a10>"
            ]
          },
          "metadata": {},
          "execution_count": 47
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPsAAAD4CAYAAAAq5pAIAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAR1klEQVR4nO3db2yVdZYH8O+xgNqCBaxA+RPBESOTjVvWikbRjI4Q9IUwanB4scGo24kZk5lkTNa4L8bEFxLdmcm+IJN01AyzzjqZZCBi/DcMmcTdFEcqYdtKd0ZACK2lBUFoS6EUzr7og+lgn3Pqfe69z5Xz/SSk7T393fvrvf1yb+95fs9PVBVEdOm7LO8JEFF5MOxEQTDsREEw7ERBMOxEQUwq542JCN/6JyoxVZXxLs/0zC4iq0TkryKyV0SeyXJdRFRaUmifXUSqAPwNwAoAXQB2AlinqnuMMXxmJyqxUjyzLwOwV1X3q+owgN8BWJ3h+oiohLKEfR6AQ2O+7kou+zsi0iQirSLSmuG2iCijkr9Bp6rNAJoBvownylOWZ/ZuAAvGfD0/uYyIKlCWsO8EsFhEFonIFADfB7C1ONMiomIr+GW8qo6IyFMA3gNQBeBVVf24aDMjoqIquPVW0I3xb3aikivJQTVE9M3BsBMFwbATBcGwEwXBsBMFwbATBcGwEwXBsBMFwbATBcGwEwXBsBMFwbATBcGwEwVR1lNJU/mJjLsA6ktZVz1OmzbNrC9fvjy19s4772S6be9nq6qqSq2NjIxkuu2svLlbCn3M+MxOFATDThQEw04UBMNOFATDThQEw04UBMNOFAT77Je4yy6z/z8/d+6cWb/++uvN+hNPPGHWh4aGUmuDg4Pm2NOnT5v1Dz/80Kxn6aV7fXDvfvXGZ5mbdfyA9XjymZ0oCIadKAiGnSgIhp0oCIadKAiGnSgIhp0oCPbZL3FWTxbw++z33HOPWb/33nvNeldXV2rt8ssvN8dWV1eb9RUrVpj1l19+ObXW29trjvXWjHv3m2fq1KmptfPnz5tjT506VdBtZgq7iBwA0A/gHIARVW3Mcn1EVDrFeGa/W1WPFuF6iKiE+Dc7URBZw64A/igiH4lI03jfICJNItIqIq0Zb4uIMsj6Mn65qnaLyCwA20Tk/1T1/bHfoKrNAJoBQESynd2QiAqW6ZldVbuTj30AtgBYVoxJEVHxFRx2EakRkWkXPgewEkBHsSZGRMWV5WX8bABbknW7kwD8l6q+W5RZUdEMDw9nGn/LLbeY9YULF5p1q8/vrQl/7733zPrSpUvN+osvvphaa22130Jqb283652dnWZ92TL7Ra51v7a0tJhjd+zYkVobGBhIrRUcdlXdD+AfCx1PROXF1htREAw7URAMO1EQDDtREAw7URCSdcver3VjPIKuJKzTFnuPr7dM1GpfAcD06dPN+tmzZ1Nr3lJOz86dO8363r17U2tZW5L19fVm3fq5AXvuDz/8sDl248aNqbXW1lacPHly3F8IPrMTBcGwEwXBsBMFwbATBcGwEwXBsBMFwbATBcE+ewXwtvfNwnt8P/jgA7PuLWH1WD+bt21x1l64teWz1+PftWuXWbd6+ID/s61atSq1dt1115lj582bZ9ZVlX12osgYdqIgGHaiIBh2oiAYdqIgGHaiIBh2oiC4ZXMFKOexDhc7fvy4WffWbQ8NDZl1a1vmSZPsXz9rW2PA7qMDwJVXXpla8/rsd955p1m//fbbzbp3muxZs2al1t59tzRnZOczO1EQDDtREAw7URAMO1EQDDtREAw7URAMO1EQ7LMHV11dbda9frFXP3XqVGrtxIkT5tjPP//crHtr7a3jF7xzCHg/l3e/nTt3zqxbff4FCxaYYwvlPrOLyKsi0iciHWMumyki20Tkk+TjjJLMjoiKZiIv438N4OLTajwDYLuqLgawPfmaiCqYG3ZVfR/AsYsuXg1gU/L5JgBrijwvIiqyQv9mn62qPcnnhwHMTvtGEWkC0FTg7RBRkWR+g05V1TqRpKo2A2gGeMJJojwV2nrrFZF6AEg+9hVvSkRUCoWGfSuA9cnn6wG8UZzpEFGpuC/jReR1AN8BUCciXQB+CmADgN+LyOMADgJYW8pJXuqy9nytnq63Jnzu3Llm/cyZM5nq1np277zwVo8e8PeGt/r0Xp98ypQpZr2/v9+s19bWmvW2trbUmveYNTY2ptb27NmTWnPDrqrrUkrf9cYSUeXg4bJEQTDsREEw7ERBMOxEQTDsREFwiWsF8E4lXVVVZdat1tsjjzxijp0zZ45ZP3LkiFm3TtcM2Es5a2pqzLHeUk+vdWe1/c6ePWuO9U5z7f3cV199tVnfuHFjaq2hocEca83NauPymZ0oCIadKAiGnSgIhp0oCIadKAiGnSgIhp0oCCnndsE8U834vJ7uyMhIwdd96623mvW33nrLrHtbMmc5BmDatGnmWG9LZu9U05MnTy6oBvjHAHhbXXusn+2ll14yx7722mtmXVXHbbbzmZ0oCIadKAiGnSgIhp0oCIadKAiGnSgIhp0oiG/UenZrra7X7/VOx+ydztla/2yt2Z6ILH10z9tvv23WBwcHzbrXZ/dOuWwdx+Gtlfce0yuuuMKse2vWs4z1HnNv7jfddFNqzdvKulB8ZicKgmEnCoJhJwqCYScKgmEnCoJhJwqCYScKoqL67FnWRpeyV11qd911l1l/6KGHzPodd9yRWvO2PfbWhHt9dG8tvvWYeXPzfh+s88IDdh/eO4+DNzePd78NDAyk1h588EFz7JtvvlnQnNxndhF5VUT6RKRjzGXPiUi3iOxO/t1f0K0TUdlM5GX8rwGsGufyX6hqQ/LPPkyLiHLnhl1V3wdwrAxzIaISyvIG3VMi0pa8zJ+R9k0i0iQirSLSmuG2iCijQsP+SwDfAtAAoAfAz9K+UVWbVbVRVRsLvC0iKoKCwq6qvap6TlXPA/gVgGXFnRYRFVtBYReR+jFffg9AR9r3ElFlcM8bLyKvA/gOgDoAvQB+mnzdAEABHADwA1XtcW8sx/PGz5w506zPnTvXrC9evLjgsV7f9IYbbjDrZ86cMevWWn1vXba3z/hnn31m1r3zr1v9Zm8Pc2//9erqarPe0tKSWps6dao51jv2wVvP7q1Jt+633t5ec+ySJUvMetp5492DalR13TgXv+KNI6LKwsNliYJg2ImCYNiJgmDYiYJg2ImCqKgtm2+77TZz/PPPP59au+aaa8yx06dPN+vWUkzAXm75xRdfmGO95bdeC8lrQVmnwfZOBd3Z2WnW165da9ZbW+2joK1tmWfMSD3KGgCwcOFCs+7Zv39/as3bLrq/v9+se0tgvZam1fq76qqrzLHe7wu3bCYKjmEnCoJhJwqCYScKgmEnCoJhJwqCYScKoux9dqtfvWPHDnN8fX19as3rk3v1LKcO9k557PW6s6qtrU2t1dXVmWMfffRRs75y5Uqz/uSTT5p1a4ns6dOnzbGffvqpWbf66IC9LDnr8lpvaa/Xx7fGe8tnr732WrPOPjtRcAw7URAMO1EQDDtREAw7URAMO1EQDDtREGXts9fV1ekDDzyQWt+wYYM5ft++fak179TAXt3b/tfi9VytPjgAHDp0yKx7p3O21vJbp5kGgDlz5pj1NWvWmHVrW2TAXpPuPSY333xzprr1s3t9dO9+87Zk9ljnIPB+n6zzPhw+fBjDw8PssxNFxrATBcGwEwXBsBMFwbATBcGwEwXBsBMF4e7iWkwjIyPo6+tLrXv9ZmuNsLetsXfdXs/X6qt65/k+duyYWT948KBZ9+ZmrZf31ox757TfsmWLWW9vbzfrVp/d20bb64V75+u3tqv2fm5vTbnXC/fGW312r4dvbfFt3SfuM7uILBCRP4vIHhH5WER+lFw+U0S2icgnyUf7jP9ElKuJvIwfAfATVf02gNsA/FBEvg3gGQDbVXUxgO3J10RUodywq2qPqu5KPu8H0AlgHoDVADYl37YJgH1cJRHl6mu9QSciCwEsBfAXALNVtScpHQYwO2VMk4i0ikir9zcYEZXOhMMuIlMB/AHAj1X15Niajq6mGXdFjao2q2qjqjZmXTxARIWbUNhFZDJGg/5bVd2cXNwrIvVJvR5A+tvsRJQ7t/Umoz2CVwB0qurPx5S2AlgPYEPy8Q3vuoaHh9Hd3Z1a95bbdnV1pdZqamrMsd4plb02ztGjR1NrR44cMcdOmmTfzd7yWq/NYy0z9U5p7C3ltH5uAFiyZIlZHxwcTK157dDjx4+bde9+s+ZuteUAvzXnjfe2bLaWFp84ccIc29DQkFrr6OhIrU2kz34HgH8G0C4iu5PLnsVoyH8vIo8DOAjA3sibiHLlhl1V/wdA2hEA3y3udIioVHi4LFEQDDtREAw7URAMO1EQDDtREGVd4jo0NITdu3en1jdv3pxaA4DHHnssteadbtnb3tdbCmotM/X64F7P1Tuy0NsS2lre621V7R3b4G1l3dPTY9at6/fm5h2fkOUxy7p8NsvyWsDu4y9atMgc29vbW9Dt8pmdKAiGnSgIhp0oCIadKAiGnSgIhp0oCIadKIiybtksIplu7L777kutPf300+bYWbNmmXVv3bbVV/X6xV6f3Ouze/1m6/qtUxYDfp/dO4bAq1s/mzfWm7vHGm/1qifCe8y8U0lb69nb2trMsWvX2qvJVZVbNhNFxrATBcGwEwXBsBMFwbATBcGwEwXBsBMFUfY+u3Wecq83mcXdd99t1l944QWzbvXpa2trzbHeudm9PrzXZ/f6/BZrC23A78Nb+wAA9mM6MDBgjvXuF481d2+9ubeO33tMt23bZtY7OztTay0tLeZYD/vsRMEx7ERBMOxEQTDsREEw7ERBMOxEQTDsREG4fXYRWQDgNwBmA1AAzar6HyLyHIB/AXBhc/JnVfVt57rK19QvoxtvvNGsZ90bfv78+Wb9wIEDqTWvn7xv3z6zTt88aX32iWwSMQLgJ6q6S0SmAfhIRC4cMfALVf33Yk2SiEpnIvuz9wDoST7vF5FOAPNKPTEiKq6v9Te7iCwEsBTAX5KLnhKRNhF5VURmpIxpEpFWEWnNNFMiymTCYReRqQD+AODHqnoSwC8BfAtAA0af+X823jhVbVbVRlVtLMJ8iahAEwq7iEzGaNB/q6qbAUBVe1X1nKqeB/ArAMtKN00iysoNu4yeovMVAJ2q+vMxl9eP+bbvAego/vSIqFgm0npbDuC/AbQDuLBe8VkA6zD6El4BHADwg+TNPOu6LsnWG1ElSWu9faPOG09EPq5nJwqOYScKgmEnCoJhJwqCYScKgmEnCoJhJwqCYScKgmEnCoJhJwqCYScKgmEnCoJhJwqCYScKYiJnly2mowAOjvm6LrmsElXq3Cp1XgDnVqhizu3atEJZ17N/5cZFWiv13HSVOrdKnRfAuRWqXHPjy3iiIBh2oiDyDntzzrdvqdS5Veq8AM6tUGWZW65/sxNR+eT9zE5EZcKwEwWRS9hFZJWI/FVE9orIM3nMIY2IHBCRdhHZnff+dMkeen0i0jHmspkisk1EPkk+jrvHXk5ze05EupP7breI3J/T3BaIyJ9FZI+IfCwiP0ouz/W+M+ZVlvut7H+zi0gVgL8BWAGgC8BOAOtUdU9ZJ5JCRA4AaFTV3A/AEJG7AAwA+I2q/kNy2YsAjqnqhuQ/yhmq+q8VMrfnAAzkvY13sltR/dhtxgGsAfAocrzvjHmtRRnutzye2ZcB2Kuq+1V1GMDvAKzOYR4VT1XfB3DsootXA9iUfL4Jo78sZZcyt4qgqj2quiv5vB/AhW3Gc73vjHmVRR5hnwfg0Jivu1BZ+70rgD+KyEci0pT3ZMYxe8w2W4cBzM5zMuNwt/Eup4u2Ga+Y+66Q7c+z4ht0X7VcVf8JwH0Afpi8XK1IOvo3WCX1Tie0jXe5jLPN+JfyvO8K3f48qzzC3g1gwZiv5yeXVQRV7U4+9gHYgsrbirr3wg66yce+nOfzpUraxnu8bcZRAfddntuf5xH2nQAWi8giEZkC4PsAtuYwj68QkZrkjROISA2Alai8rai3AliffL4ewBs5zuXvVMo23mnbjCPn+y737c9Vtez/ANyP0Xfk9wH4tzzmkDKv6wD8b/Lv47znBuB1jL6sO4vR9zYeB3A1gO0APgHwJwAzK2hu/4nRrb3bMBqs+pzmthyjL9HbAOxO/t2f931nzKss9xsPlyUKgm/QEQXBsBMFwbATBcGwEwXBsBMFwbATBcGwEwXx//5fN5ZQVuVBAAAAAElFTkSuQmCC\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# model_2.state_dict()"
      ],
      "metadata": {
        "id": "jb1hQxyCrIfI"
      },
      "execution_count": 48,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 7.1 Stepping through `nn.Conv2d()`\n",
        "\n",
        "See the documentation for `nn.Conv2d()` here - https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html "
      ],
      "metadata": {
        "id": "94pDgbEdoc4t"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "torch.manual_seed(42)\n",
        "\n",
        "# Create a batch of images\n",
        "images = torch.randn(size=(32, 3, 64, 64))\n",
        "test_image = images[0] \n",
        "\n",
        "print(f\"Image batch shape: {images.shape}\")\n",
        "print(f\"Single image shape: {test_image.shape}\")\n",
        "print(f\"Test image:\\n {test_image}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "F2ygb4FWqdYt",
        "outputId": "1824c067-ec57-4ad8-c239-5f54fa0896c0"
      },
      "execution_count": 49,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Image batch shape: torch.Size([32, 3, 64, 64])\n",
            "Single image shape: torch.Size([3, 64, 64])\n",
            "Test image:\n",
            " tensor([[[ 1.9269,  1.4873,  0.9007,  ...,  1.8446, -1.1845,  1.3835],\n",
            "         [ 1.4451,  0.8564,  2.2181,  ...,  0.3399,  0.7200,  0.4114],\n",
            "         [ 1.9312,  1.0119, -1.4364,  ..., -0.5558,  0.7043,  0.7099],\n",
            "         ...,\n",
            "         [-0.5610, -0.4830,  0.4770,  ..., -0.2713, -0.9537, -0.6737],\n",
            "         [ 0.3076, -0.1277,  0.0366,  ..., -2.0060,  0.2824, -0.8111],\n",
            "         [-1.5486,  0.0485, -0.7712,  ..., -0.1403,  0.9416, -0.0118]],\n",
            "\n",
            "        [[-0.5197,  1.8524,  1.8365,  ...,  0.8935, -1.5114, -0.8515],\n",
            "         [ 2.0818,  1.0677, -1.4277,  ...,  1.6612, -2.6223, -0.4319],\n",
            "         [-0.1010, -0.4388, -1.9775,  ...,  0.2106,  0.2536, -0.7318],\n",
            "         ...,\n",
            "         [ 0.2779,  0.7342, -0.3736,  ..., -0.4601,  0.1815,  0.1850],\n",
            "         [ 0.7205, -0.2833,  0.0937,  ..., -0.1002, -2.3609,  2.2465],\n",
            "         [-1.3242, -0.1973,  0.2920,  ...,  0.5409,  0.6940,  1.8563]],\n",
            "\n",
            "        [[-0.7978,  1.0261,  1.1465,  ...,  1.2134,  0.9354, -0.0780],\n",
            "         [-1.4647, -1.9571,  0.1017,  ..., -1.9986, -0.7409,  0.7011],\n",
            "         [-1.3938,  0.8466, -1.7191,  ..., -1.1867,  0.1320,  0.3407],\n",
            "         ...,\n",
            "         [ 0.8206, -0.3745,  1.2499,  ..., -0.0676,  0.0385,  0.6335],\n",
            "         [-0.5589, -0.3393,  0.2347,  ...,  2.1181,  2.4569,  1.3083],\n",
            "         [-0.4092,  1.5199,  0.2401,  ..., -0.2558,  0.7870,  0.9924]]])\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "test_image.shape"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "uBIyn2aWrb6T",
        "outputId": "dad30974-5bdc-428b-818c-811c127ae35c"
      },
      "execution_count": 50,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([3, 64, 64])"
            ]
          },
          "metadata": {},
          "execution_count": 50
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "torch.manual_seed(42)\n",
        "# Create a sinlge conv2d layer\n",
        "conv_layer = nn.Conv2d(in_channels=3, \n",
        "                       out_channels=10,\n",
        "                       kernel_size=(3, 3),\n",
        "                       stride=1,\n",
        "                       padding=0)\n",
        "\n",
        "# Pass the data through the convolutional layer \n",
        "conv_output = conv_layer(test_image.unsqueeze(0))\n",
        "conv_output.shape"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "W8b2rAx-rAFa",
        "outputId": "aacdbfd2-8028-47da-85a7-e5aaedce55c7"
      },
      "execution_count": 51,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([1, 10, 62, 62])"
            ]
          },
          "metadata": {},
          "execution_count": 51
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "test_image.unsqueeze(0).shape"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ef-y24bus4hP",
        "outputId": "7eefe4bd-a9a1-4ecd-b047-0a743417f927"
      },
      "execution_count": 52,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([1, 3, 64, 64])"
            ]
          },
          "metadata": {},
          "execution_count": 52
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 7.2 Stepping through `nn.MaxPool2d()`\n",
        "\n",
        "https://pytorch.org/docs/stable/generated/torch.nn.MaxPool2d.html\n"
      ],
      "metadata": {
        "id": "1QEgTbW1tFXJ"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "test_image.shape"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "iHzuNz2lFt80",
        "outputId": "5222bb76-8837-4539-8c87-be136269acd0"
      },
      "execution_count": 53,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([3, 64, 64])"
            ]
          },
          "metadata": {},
          "execution_count": 53
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Print out original image shape without unsqueezed dimension\n",
        "print(f\"Test image original shape: {test_image.shape}\")\n",
        "print(f\"Test image with unsqueezed dimension: {test_image.unsqueeze(0).shape}\")\n",
        "\n",
        "# Create a sample nn.MaxPool2d layer\n",
        "max_pool_layer = nn.MaxPool2d(kernel_size=2)\n",
        "\n",
        "# Pass data through just the conv_layer\n",
        "test_image_through_conv = conv_layer(test_image.unsqueeze(dim=0))\n",
        "print(f\"Shape after going through conv_layer(): {test_image_through_conv.shape}\")\n",
        "\n",
        "# Pass data through the max pool layer\n",
        "test_image_through_conv_and_max_pool = max_pool_layer(test_image_through_conv)\n",
        "print(f\"Shape after going through conv_layer() and max_pool_layer(): {test_image_through_conv_and_max_pool.shape}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "bdfe9lrbFdDF",
        "outputId": "1f8c56e8-f86a-481c-9437-fc1b24e8463e"
      },
      "execution_count": 54,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Test image original shape: torch.Size([3, 64, 64])\n",
            "Test image with unsqueezed dimension: torch.Size([1, 3, 64, 64])\n",
            "Shape after going through conv_layer(): torch.Size([1, 10, 62, 62])\n",
            "Shape after going through conv_layer() and max_pool_layer(): torch.Size([1, 10, 31, 31])\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "torch.manual_seed(42)\n",
        "# Create a random tesnor with a similar number of dimensions to our images\n",
        "random_tensor = torch.randn(size=(1, 1, 2, 2))\n",
        "print(f\"\\nRandom tensor:\\n{random_tensor}\")\n",
        "print(f\"Random tensor shape: {random_tensor.shape}\")\n",
        "\n",
        "# Create a max pool layer\n",
        "max_pool_layer = nn.MaxPool2d(kernel_size=2)\n",
        "\n",
        "# Pass the random tensor through the max pool layer\n",
        "max_pool_tensor = max_pool_layer(random_tensor)\n",
        "print(f\"\\nMax pool tensor:\\n {max_pool_tensor}\")\n",
        "print(f\"Max pool tensor shape: {max_pool_tensor.shape}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "hPYRut1CGsBw",
        "outputId": "553c6e35-3ecd-4c22-d639-edcf8606e532"
      },
      "execution_count": 55,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\n",
            "Random tensor:\n",
            "tensor([[[[0.3367, 0.1288],\n",
            "          [0.2345, 0.2303]]]])\n",
            "Random tensor shape: torch.Size([1, 1, 2, 2])\n",
            "\n",
            "Max pool tensor:\n",
            " tensor([[[[0.3367]]]])\n",
            "Max pool tensor shape: torch.Size([1, 1, 1, 1])\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 7.3 Setup a loss function and optimizer for `model_2`"
      ],
      "metadata": {
        "id": "Ct7otCmGGt77"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Setup loss function/eval metrics/optimizer\n",
        "from helper_functions import accuracy_fn\n",
        "\n",
        "loss_fn = nn.CrossEntropyLoss()\n",
        "optimizer = torch.optim.SGD(params=model_2.parameters(),\n",
        "                            lr=0.1)"
      ],
      "metadata": {
        "id": "a28lIFuhPjhq"
      },
      "execution_count": 56,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 7.4 Training and testing `model_2` using our training and test functions"
      ],
      "metadata": {
        "id": "V1zGMo07P4vE"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "torch.manual_seed(42)\n",
        "torch.cuda.manual_seed(42)\n",
        "\n",
        "# Measure time\n",
        "from timeit import default_timer as timer\n",
        "train_time_start_model_2 = timer() \n",
        "\n",
        "# Train and test model\n",
        "epochs = 3\n",
        "for epoch in tqdm(range(epochs)):\n",
        "  print(f\"Epoch: {epoch}\\n-------\")\n",
        "  train_step(model=model_2,\n",
        "             data_loader=train_dataloader,\n",
        "             loss_fn=loss_fn,\n",
        "             optimizer=optimizer,\n",
        "             accuracy_fn=accuracy_fn,\n",
        "             device=device)\n",
        "  test_step(model=model_2,\n",
        "            data_loader=test_dataloader,\n",
        "            loss_fn=loss_fn,\n",
        "            accuracy_fn=accuracy_fn,\n",
        "            device=device)\n",
        "\n",
        "train_time_end_model_2 = timer()\n",
        "total_train_time_model_2 = print_train_time(start=train_time_start_model_2,\n",
        "                                            end=train_time_end_model_2,\n",
        "                                            device=device)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 333,
          "referenced_widgets": [
            "68711c9d9d1642fcaa2b2e315bfd397d",
            "04aea2c27e7d474c9b90d0652a9c1cf5",
            "a740c3de6c59407d81ddf303cfca6477",
            "5acae86e9528489a9ab1c644669732c2",
            "2c2a8fa51d7a4a4db851f95e5ea89fa9",
            "e6a36256789748a3850fe3d011be8849",
            "0298028987a14b69a1170c517aed5f5a",
            "94aaeb0786484fd38fbb10380a7d891c",
            "9bd2f35f1aa649d7820c5bb47896dd1a",
            "fc46fa93b44b4212aa25158905ac411b",
            "c4fb9e39bef348f8bbee3cc67195013a"
          ]
        },
        "id": "2F8UYzU7QXEG",
        "outputId": "544d7973-4582-43e9-d899-2189aa83a29f"
      },
      "execution_count": 57,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "  0%|          | 0/3 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "68711c9d9d1642fcaa2b2e315bfd397d"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Epoch: 0\n",
            "-------\n",
            "Train loss: 0.59952 | Train acc: 78.09%\n",
            "Test loss: 0.38754 | Test acc: 85.94%\n",
            "\n",
            "Epoch: 1\n",
            "-------\n",
            "Train loss: 0.35734 | Train acc: 87.07%\n",
            "Test loss: 0.34306 | Test acc: 87.63%\n",
            "\n",
            "Epoch: 2\n",
            "-------\n",
            "Train loss: 0.31825 | Train acc: 88.42%\n",
            "Test loss: 0.31359 | Test acc: 88.57%\n",
            "\n",
            "Train time on cuda: 32.770 seconds\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Get model_2 results\n",
        "model_2_results = eval_model(\n",
        "     model=model_2,\n",
        "     data_loader=test_dataloader,\n",
        "     loss_fn=loss_fn,\n",
        "     accuracy_fn=accuracy_fn,\n",
        "     device=device\n",
        ")\n",
        "\n",
        "model_2_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 102,
          "referenced_widgets": [
            "b20785d11eac4ecd88c2d1fcf5f87e99",
            "4a8c9a109c324cb6b285fe655a7b7a52",
            "1de0bde77ecd4a5aa2831ac3e767522a",
            "c292425b6491436bb09d6b526a3f05d3",
            "ef71a3d209ef4e80863df4076f3fc6b3",
            "48df394b8e0244fb9a55ce99908a6857",
            "006deca9eded4d18881cc81ec34650a3",
            "74a40d51368b4f00a83917bee93cab1a",
            "40e05f64efd744afbc227e7bf399a8e7",
            "d78d6d8d2d9a4611aecb70126668c237",
            "002fad04387e410e9907948bbe1975b3"
          ]
        },
        "id": "ToWV1EJjRvW_",
        "outputId": "e44f2d6a-957a-424b-919e-d9c72984a6b7"
      },
      "execution_count": 58,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "  0%|          | 0/313 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "b20785d11eac4ecd88c2d1fcf5f87e99"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'model_acc': 88.56829073482429,\n",
              " 'model_loss': 0.31358689069747925,\n",
              " 'model_name': 'FashionMNISTModelV2'}"
            ]
          },
          "metadata": {},
          "execution_count": 58
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 8. Compare model results and training time "
      ],
      "metadata": {
        "id": "6o3QEmmaSEhx"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import pandas as pd\n",
        "compare_results = pd.DataFrame([model_0_results,\n",
        "                                model_1_results,\n",
        "                                model_2_results])\n",
        "compare_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 143
        },
        "id": "se1fcb05TAWu",
        "outputId": "9ac7af95-1d36-4f9c-fbc6-ca993f2ee167"
      },
      "execution_count": 59,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "            model_name  model_loss  model_acc\n",
              "0  FashionMNISTModelV0    0.476639  83.426518\n",
              "1  FashionMNISTModelV1    0.685001  75.019968\n",
              "2  FashionMNISTModelV2    0.313587  88.568291"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-2db41ec5-3a31-4801-a1d3-5bfb471009d5\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>model_name</th>\n",
              "      <th>model_loss</th>\n",
              "      <th>model_acc</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>FashionMNISTModelV0</td>\n",
              "      <td>0.476639</td>\n",
              "      <td>83.426518</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>FashionMNISTModelV1</td>\n",
              "      <td>0.685001</td>\n",
              "      <td>75.019968</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>FashionMNISTModelV2</td>\n",
              "      <td>0.313587</td>\n",
              "      <td>88.568291</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-2db41ec5-3a31-4801-a1d3-5bfb471009d5')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-2db41ec5-3a31-4801-a1d3-5bfb471009d5 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-2db41ec5-3a31-4801-a1d3-5bfb471009d5');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 59
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Add training time to results comparison\n",
        "compare_results[\"training_time\"] = [total_train_time_model_0,\n",
        "                                    total_train_time_model_1,\n",
        "                                    total_train_time_model_2]\n",
        "compare_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 143
        },
        "id": "aogpUEOlTKsZ",
        "outputId": "ebf995ff-1956-4292-f5ae-3064f0c7680e"
      },
      "execution_count": 60,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "            model_name  model_loss  model_acc  training_time\n",
              "0  FashionMNISTModelV0    0.476639  83.426518      26.748773\n",
              "1  FashionMNISTModelV1    0.685001  75.019968      20.041531\n",
              "2  FashionMNISTModelV2    0.313587  88.568291      32.770459"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-55295f49-2182-4da0-9688-f7de4e943f32\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>model_name</th>\n",
              "      <th>model_loss</th>\n",
              "      <th>model_acc</th>\n",
              "      <th>training_time</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>FashionMNISTModelV0</td>\n",
              "      <td>0.476639</td>\n",
              "      <td>83.426518</td>\n",
              "      <td>26.748773</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>FashionMNISTModelV1</td>\n",
              "      <td>0.685001</td>\n",
              "      <td>75.019968</td>\n",
              "      <td>20.041531</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>FashionMNISTModelV2</td>\n",
              "      <td>0.313587</td>\n",
              "      <td>88.568291</td>\n",
              "      <td>32.770459</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-55295f49-2182-4da0-9688-f7de4e943f32')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-55295f49-2182-4da0-9688-f7de4e943f32 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-55295f49-2182-4da0-9688-f7de4e943f32');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 60
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Visualize our model results\n",
        "compare_results.set_index(\"model_name\")[\"model_acc\"].plot(kind=\"barh\")\n",
        "plt.xlabel(\"accuracy (%)\")\n",
        "plt.ylabel(\"model\");"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 279
        },
        "id": "DK8M3lsIT9Hz",
        "outputId": "70cbe6a4-b56d-4a74-e265-fcb4d70493d2"
      },
      "execution_count": 61,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 9. Make and evaluate random predictions with best model"
      ],
      "metadata": {
        "id": "WQgODWGjUZdk"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "def make_predictions(model: torch.nn.Module,\n",
        "                     data: list,\n",
        "                     device: torch.device = device):\n",
        "  pred_probs = []\n",
        "  model.to(device)\n",
        "  model.eval()\n",
        "  with torch.inference_mode():\n",
        "    for sample in data:\n",
        "      # Prepare the sample (add a batch dimension and pass to target device)\n",
        "      sample = torch.unsqueeze(sample, dim=0).to(device)\n",
        "\n",
        "      # Forward pass (model outputs raw logits)\n",
        "      pred_logit = model(sample)\n",
        "\n",
        "      # Get prediction probability (logit -> prediction probability)\n",
        "      pred_prob = torch.softmax(pred_logit.squeeze(), dim=0)\n",
        "\n",
        "      # Get pred_prob off the GPU for further calculations\n",
        "      pred_probs.append(pred_prob.cpu())\n",
        "\n",
        "  # Stack the pred_probs to turn list into a tensor\n",
        "  return torch.stack(pred_probs)"
      ],
      "metadata": {
        "id": "V1lL4W0a7iop"
      },
      "execution_count": 62,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "import random\n",
        "# random.seed(42)\n",
        "test_samples = [] \n",
        "test_labels = []\n",
        "for sample, label in random.sample(list(test_data), k=9):\n",
        "  test_samples.append(sample)\n",
        "  test_labels.append(label)\n",
        "\n",
        "# View the first sample shape\n",
        "test_samples[0].shape"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "j57BojmB8muV",
        "outputId": "04ebee0a-039a-4597-d6ff-f8fc770649b4"
      },
      "execution_count": 63,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "torch.Size([1, 28, 28])"
            ]
          },
          "metadata": {},
          "execution_count": 63
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "plt.imshow(test_samples[0].squeeze(), cmap=\"gray\")\n",
        "plt.title(class_names[test_labels[0]])"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 299
        },
        "id": "TOV5vS_Z9LL6",
        "outputId": "4e8c7933-2dfa-456c-e645-96f7d939e2ef"
      },
      "execution_count": 64,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "Text(0.5, 1.0, 'Dress')"
            ]
          },
          "metadata": {},
          "execution_count": 64
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Make predictions\n",
        "pred_probs = make_predictions(model=model_2,\n",
        "                              data=test_samples)\n",
        "\n",
        "# View first two prediction probabilities\n",
        "pred_probs[:2]"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "dUuIC6O69MRg",
        "outputId": "e95d2f66-19ff-4625-be1d-f28988a1b738"
      },
      "execution_count": 65,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[1.2333e-03, 3.3934e-03, 4.5061e-05, 9.8818e-01, 6.3306e-03, 7.6291e-06,\n",
              "         3.1144e-04, 3.5785e-04, 7.5017e-05, 6.2114e-05],\n",
              "        [1.6455e-03, 2.8294e-05, 9.6235e-01, 2.9167e-04, 1.0726e-03, 3.6521e-06,\n",
              "         3.4579e-02, 1.1791e-06, 2.2558e-05, 6.7034e-06]])"
            ]
          },
          "metadata": {},
          "execution_count": 65
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Convert prediction probabilities to labels\n",
        "pred_classes = pred_probs.argmax(dim=1)\n",
        "pred_classes"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "uMcLHQGL9n4v",
        "outputId": "c3f2b89a-e28c-43ba-c79f-7968abd5f425"
      },
      "execution_count": 66,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([3, 2, 3, 0, 7, 1, 1, 5, 4])"
            ]
          },
          "metadata": {},
          "execution_count": 66
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "test_labels"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "gix-TY_59tBY",
        "outputId": "8b0e35da-8ff8-48a5-f78b-298cab2193c1"
      },
      "execution_count": 67,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[3, 2, 3, 0, 9, 1, 1, 5, 4]"
            ]
          },
          "metadata": {},
          "execution_count": 67
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Plot predictions\n",
        "plt.figure(figsize=(9, 9))\n",
        "nrows = 3\n",
        "ncols = 3\n",
        "for i, sample in enumerate(test_samples):\n",
        "  # Create subplot\n",
        "  plt.subplot(nrows, ncols, i+1)\n",
        "\n",
        "  # Plot the target image\n",
        "  plt.imshow(sample.squeeze(), cmap=\"gray\")\n",
        "\n",
        "  # Find the prediction (in text form, e.g \"Sandal\")\n",
        "  pred_label = class_names[pred_classes[i]]\n",
        "\n",
        "  # Get the truth label (in text form) \n",
        "  truth_label = class_names[test_labels[i]]\n",
        "\n",
        "  # Create a title for the plot\n",
        "  title_text = f\"Pred: {pred_label} | Truth: {truth_label}\"\n",
        "\n",
        "  # Check for equality between pred and truth and change color of title text\n",
        "  if pred_label == truth_label:\n",
        "    plt.title(title_text, fontsize=10, c=\"g\") # green text if prediction same as truth\n",
        "  else:\n",
        "    plt.title(title_text, fontsize=10, c=\"r\") \n",
        "  \n",
        "  plt.axis(False);"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 534
        },
        "id": "-073m90P96fW",
        "outputId": "e6c64e5c-4327-4d25-ac77-fba8bfb0ab9d"
      },
      "execution_count": 68,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 648x648 with 9 Axes>"
            ],
            "image/png": "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AABANBIHAAAQjcQBAABEI3EAAADR2lxxpGXXXXcNYlZRjTXLY1GBYmxhZmwfY4sjrdkgJbugyFq/d+/eQWz06NFBzCqObEgBGtoWa8ycccYZQcx6/PC4cePMbW622WYV96e5ChyZPbXpbbHFFkGsW7du5rKdO3cOYlYh5Ouvv17xup988kkQswompeJi+raGKw4AACAaiQMAAIhG4gAAAKKROAAAgGjtojjSKqyxZo60YkVtNMeMibEzUUr2rI5WcaRVgLbnnntW0Du0F1tttVUQu/DCC4OYNUtkdXV1ELvsssvMdkaNGhXErKLf5cuXB7E5c+YEMWvm1IYetxRCNr01a9YEsWXLlpnLWgXt/fv3D2J33nlnELMKfK3zqDWOiormZ82aZcbbGq44AACAaCQOAAAgGokDAACIRuIAAACitYviSGsmMuuxqFZxZJcuXcxtWo9kbUjhVOyMdFbxjmT389NPP41q+913341ajsKw9qlv375BzCoCmzhxYhDr2bNnECuaBfCEE04IYlYxr3UMdOrUKYhZx7NVHFn0yGbrEclz584NYuPHjzfXR2Ws4kirIFaSOnbsGMSsMdO9e/cgZs3+OH369CBmjbeiIlurkLIt4ooDAACIRuIAAACikTgAAIBoJA4AACBaqy6OtGYNs9x7771B7O677w5iVtFWUbGL9fhUqxjRKnq0im1iH8ldToGiVTi0YsWKIGbNqmahOLJtscbhkUceGcR23333IGYVQg4cODCIWbNOWo8pluyxac0YGPsIeqs4MrZQWrKLQq3XSHFk47LOuUVF4dY5zopZBZfWchbrXG89kluyx1xbxBUHAAAQjcQBAABEI3EAAADRSBwAAEA0EgcAABCtVZeANqTK/+qrrw5iF154YRCzppaW4qe7tpaLXbecdletWhXErApya5rV1atXR7XNXRVty/Dhw4PYxRdfHMQeeuihIGZNJR07jXuPHj3M/ljb7N27dxCz7r6wphlevHhxEIu9G0qyX8+kSZPMZdF4iu6gsBQ9EqC2hQsXBjHrThxrfFjTSxedh2On+W/tuOIAAACikTgAAIBoJA4AACAaiQMAAIjWqosjLVZhjVUE8+ijjwaxCy64IGp7UnzBTOz00pbYaaiL+mMVDn3wwQdRbcf2By3ftttua8avuOKKIGYdF5MnTw5io0aNCmLWeLOKI4um5f3444/NeG3WdL9WbJtttgliVh+rq6vNdqxjt0+fPjFdRANY5+u1a9eay1rvUexU+9b5zBpHVsFj0XTVVjttEVccAABANBIHAAAQjcQBAABEI3EAAADR2lxxZOysjK+99loQswpeyimOtGYda8gskZai/ljPm7dm07OK32LbsYqW0LJst912QcyaEVWSOnXqFMSs4tn99tsviFnj3yoimzFjRhCzjpOieNeuXYOYVVw5b968qHU//PDDINatWzezP9bxUzTrJRqPNQuudX6TpHXr1kVt0zqfWbMCW2PLGutWEaXUfgrIueIAAACikTgAAIBoJA4AACAaiQMAAIjW5oojY8U+urWouNEqgrGKu2KLZRr6+G3r9VgFRVOmTKm4P+2J9fo3ZuGT9Yh06xHYhxxySBDbcccdzW0+/vjjQcwqCLSKw5YvXx7ErMIyq2DSerS7ZB8/1kx8VjvWzILWY7WtgknrtUhS9+7dg5g1GyUalzXerPdNij8mrffYGm9WoaxVFG4dJ5K0evXqqP60dlxxAAAA0UgcAABANBIHAAAQjcQBAABEa7fFkdbMX8uWLQtiRbMlNrS4stJ1i7YXW8w3e/bsivvT3sU+Ir0piijHjRsXxPr16xfEVq5cGcSsGfIk6Zlnngli1ni3HndtFQ5aBWhW0WJRf6z9axU4brXVVkHMmvXVOsarqqqCmFXAKdkFcEWPKEfjsYoWi2aOtJa1ZkQtWr82a7xas1NaxcqSPetlW8QVBwAAEI3EAQAARCNxAAAA0UgcAABAtHZbHGmxZg1bsGCBuWxs0WNjz0BYVJRpxa3XE/sY2vauuYoe+/btG8RGjBgRxAYPHhzEFi5cGMSsmQ1nzpxptm0VKVoz9FmFkNZ4swrLrAJDaznJLnSzChznzJkTxAYMGBDErH5b498qpiuKW0V2ReujMtZxVlSkbr3H1nFhbdOa5dGalXTzzTcPYlYxrmQXJ7dFXHEAAADRSBwAAEA0EgcAABCNxAEAAERrt8WRDZ3hq7FnhLTEzk4pxRfuxT72dWM+Qro1GT58eBCzihsluzDPKgjs3bt3EBsyZEgQs2Y6nTdvXhB78sknzf7stttuQaxLly5BzJo5MrbI0Cq2tIrNpPjxbvUxdjZJS9HxaM0oyWySTc+alXHgwIHmstZ7Z80OarHGh1VsaY3rooLYollI2xquOAAAgGgkDgAAIBqJAwAAiEbiAAAAopE4AACAaG3urorYuwGsymzL+vXrzbhVDW+1HTvldOydFkX9sba5fPnyILb33nsHsZdeeilqe+3JTjvtFMRuvvnmIPbuu+8GMesuBEmaO3duELPu7rGmiP7b3/4WxKw7Fqyq7kGDBpn9sVh3DVh3LPTv3z+IWXeDWFP4Ft09YR1T1h0Y1uu21l2xYoXZTm1WHyX7zhFraut99tknqh3Esc5xu+66q7msdR4vumunNmvq81122SWI7b///kHMuvtCKp4au63higMAAIhG4gAAAKKROAAAgGgkDgAAIFqbK46MNW7cuCBmFQQWFQnGFjNayzUkVtQfa/pUa3rps88+O4j95je/iW6nvbCmjbaK6LbbbrsgVlSMaL2fvXr1CmLWvrcK9az+WG0UFWxZ61vFlVaxmtVHa3tFhYcWa5tW21ZRm1XUacWsfWEtJ9kFl7NmzQpiK1euNNdHZWKPCUnq06dPEIud9tl636yC8u233z6IFRXXt5fzJlccAABANBIHAAAQjcQBAABEI3EAAADR2lxxZOzMXf/6r/8axBYuXBjdTmxxpMWaOS+2OLJo1j1L7MyR/fr1C2LV1dXR7bRFH330URCLLQgsKpCyCv3mz58ftb5VwGeNBWv8lzPbaCyrHWt7sX0spx2rUNQSW9QZO9OgZM8Y2N6PlcZmFTcWFbD26NEjiFnHrsUqKC9qp7b2UgRZhCsOAAAgGokDAACIRuIAAACikTgAAIBorbo40prZzSqIGjx4cBCzigStWeE6depktl1UcFap2KLHch5JbD2yecGCBUHs/vvvD2IHHXRQVH/aqtmzZwcxa99bBVZWwZZUPJZqswq0rPEWOwaLCnljC7xiZ6i0WLM8NnTWvdgZXq39Yx0nVkyyX+MOO+wQxKzHiaNyW2yxRRArGutr1qwJYlZRuMUah7HFzta5tT3higMAAIhG4gAAAKKROAAAgGgkDgAAIFqrLo6MLQ675pprgphVQGNtr6gYsZwZHGuLnRHSmjWvqF2rgMcq3Fu6dGkQGz16dBDba6+9gtiUKVPMttuimTNnBrGGFoxaM3RahZTWe2wV4FnrWmOmaKZGq7DMehS7VQhmrWsVQq5YsSKIFT1q21q/nEfL19a5c+cgZu3bopkjrWJWa9lXX301qj+IY71vRQWPW265ZRCbNm1aVDvWWLfe89iZStsTrjgAAIBoJA4AACAaiQMAAIhG4gAAAKK16uLIWMOGDQtiixcvDmKxj1SVGv+x2rGP2i4qDLMK4Kz1rUIfa19cd911QWzs2LFm24hjPX6ZRzIDX2QVKK5cudJc1ppl0irctVjnwtiid6vwvD3higMAAIhG4gAAAKKROAAAgGgkDgAAIFqbK478+c9/HsT69+8fxKxHaFuFMUXFiEWz3zWm2EcFS3ZxZOzjh61Z2fbbb78gdthhhwWxJ554wuwPAFSia9euQWzevHnmstajsa1ib4t1Li2aZTWm3faEKw4AACAaiQMAAIhG4gAAAKKROAAAgGgkDgAAIFqbu6vi+eefD2IvvvhiENt1112DmFXNaz2zXbKnNbWmeI6dCtq6o8O6c6NoStQOHTpELWtNq21VIX/88cdBrKiyGQAai3V+LHocgHWeWrRoUVQ71jat6a4//fTTIBY7rXVbxRUHAAAQjcQBAABEI3EAAADRSBwAAEC0Nlcc+dhjj0XFttlmmyD23e9+N4gdd9xxZjuDBw8OYlYxolXoE8uaHnrJkiXmsrNnzw5iU6dODWITJkwIYo8++mgQs6ahBoCm1qdPnyC2atUqc1nrPNyzZ8+odqwpp7t16xbVdt++faPaaKu44gAAAKKROAAAgGgkDgAAIBqJAwAAiNbmiiNjffTRR0Hspz/9aVQMANA05syZE8Sqq6vNZadNmxbE/vnPf0a18+GHHwaxlStXBjGrOHLp0qVRbbRVXHEAAADRSBwAAEA0EgcAABCNxAEAAERz1uyEAAAAFq44AACAaCQOAAAgGokDAACIRuIAAACikTgAAIBoJA4AACAaiQMAAIhG4gAAAKKROAAAgGgkDgAAIBqJAwAAiEbiAAAAopE4AACAaCQOAAAgGokDAACItmlTbtylbr2kN/J2/iHpWz7xKyvc1nhJE3zi7y/4+1mSfpj/c3dJ0yStl/Rnn/hLKmmzsbnUPS3pTJ/4GSWxSyWdkP9zT2X7S5Ju94m/IWKb4yS96xP/dkkbF/nEvxrZp5cldZTUS1JnSR/lfxpX2s/2rjnHcr5MP0m3SdpO0maSZvjEH1lJe7W2OyBve0gly7jUzfCJH1ArdqOkUZI2l7SjsmNPkq6q6zWWrH+mpL/4xM+paUPSSJ/4+fWtW7KNSyWdquyY/0zSd33iX45dv47tPq16jqdyj7nWornHfL7cVyVdKamLpDWSnvSJ//8qaG+MpLU+8S8YfxsgabxP/Jha8QadC13qfuwT//OSNuo8zgq2sa+kayT1k7RS0iRJ55W7313qhknq7xP/p3LWi9WkiYOkVT7xwyTJpe4eSd+TdG3NH13qNvWJX9cYDfnE3yHpjny7MySNrX3icanr4BO/vjHaq0/sa/OJ/5mkn+XrLK/ZXyXbcZKcT/xnBZsYJ2mCpLcr6adP/H55O2cqO1n/oFb7jfYexWjO96hMzTaWc1dI+qtP/PX59oc24rYblU/896UvnCxrj+H69s2Zkt6UNKeS9l3qDpB0lKThPvFrXOp6K0ti0DDNOuZd6oZI+m9JX/OJf8elroOk71S4uTGSlksKEocijXAu/LGkn5fd0w3b7yfpD5JO9ol/MY8dL6mbsiSiHMMkjZTUKhOHUs9KGppngldKWiRpV5e63ST9Utkb3VHSjT7xv8s/MP9L0pclzZa0tpJGXeqWS/qdpMMkfT/P6P4l//OtPvHX1c4OXeouklTlE3+5S915yg6YdZLe9ok/2aWua963Icq+DV7uE/9wPuC+IalKUgdJh1TY5wGSJkp6WdIISUe61L3lE1+V//14ZSfKmyUdI+kQl7qfSDou38QJLnU3Seop6ds+8c+W2f7lkgZJGihplkvdv0u6XVJvSZ9IOssnflbtbxF54lPlUre1pPskdVc2xs7xiX/Wpe5wSamy93l6vp3leaJ3n7L3+leSfl9OfzeC5hjLW0v6S80/fOKnSpJLXZWkhyVtoWzs/SQfewMkPS7pOUkHKvu29HWf+FUudSOUvX8q3Wa+zt2SuuahH1jf0Cph7JvDZRxjyhKGkZLucalbJemAfBPnutQdnb/GE3zi36mjua0lzfeJXyNJpV8YXOp+KuloZd8gX1B2JcLnVwleljRWJceJS11nZV9A9pL0Tr5ezbZ+I2mfPHa/T3xS4e5pjZpjzP+bpJ/VvNf5F4jfSJ+PVescdLSknyhLFBdIOk3Z+/M9Setd6k6XdG6558AaxrlwokqSCpe6CcquEBwhqbNL3WRJb0m6VFIHl7pbVOt4rKO570u6syZpyPdBzbm1V/76BypLIr7jEz81/zy7XlInSasknSXpA2VfPDq71I2W9Auf+Psqef1FmqXGwaVuU0lf1YbL8MMl/dAnfrCkb0ta4hO/j7KD8myXuh0lHStpF2U/O5yhbOfXbO8Kl7pjIpvvKulln/i9tGHH7idp/7ytvetZ/xJJe/vED1U2GKVsUDzpE7+vshPP1XkyUfPajveJryhpKLGzpJt84vfwiZ9pLZCf5B+RdLFP/DCf+On5nzbN+3a+pESSXOr6u9SVk33uLukwn/hTlJ0A7sz3wT2S6vsJ5VRJE/NvK3tJmpx/C/xJvs3hkl6VdGHJOgt84of7xLfopKEZx/KNkm5zqXvKpe5Sl7r+eXy1pGPzfThW0n/mJ2kpGzM3+sTvIWmxNiSSdyg7ee5Vq415kr6cb+sk1f++lqt035jyE+Orkk7Lx3DNiXV+3q/fSLpIklzqRrrU3Wps5i+StnOpe9el7iaXutJj77994vfJE5bOyhLuGsFxIukcSSt94nfLYyNKlr/UJ36kpKHKkvUWexWoMTXjmB+i7NK8pegcSX0uGgAAGPJJREFU9Jyk/X3i91b2hePf8p8Vfivp1/mYqihpKFF6LjT57OfwVXl7p+Vh83h0qfueS933jM3U9fpTSa/nr//Hku7K4+9IOih//T+V9HOf+LX5f9+X96dRkwap6a841GRgUpax3qZsAL3iE/9BHj9cWSZ7fP7vHsp2+MGS7s2zzjkudU/WbNQn/qdl9GG9pD/m/z1a0oM+8SskyaXuAUkHKfvwLTJV2behhyQ9VNLnY/JvTVKW7W2f//dffeIXltG/IjN94l+qcN0H8v+fJGmAJPns9+NyfiN/pOQkfoCyKylS9g31V/Ws+3dJt7vUbSbpIZ/4yfnJfHdJz7vUSdk3hBdL1mn0wd3ImnUs+8RPdKkbqOybzFclvZ5fyl0s6ecudQcr+y1/G2W/h0rSBz7xNX2cJGmAS11PST194v+Wx+/Otydl3+b/O/89dL2kwg/4CpXum3KVjuFvSJLPagj+T+0F86tWI5Qdy2Ml3edSd4lP/HhJY13q/k3Zb+a9lH0bfNRoY0D+3wcr/1DKv9FNLWnqRJe67yg7b26tbDyX/r2taQnn7xpF56Btlb3fWys7p1Q63upSei4sR3A8SpJP/G8r2NZo5YmHT/yTLnVbutR1V7a/73Sp21mSV3ZMN7lmq3GokX9orCgNKfs2NLHWcg0uBMut9vX/Zr5OX7z60qnkv7+m7CA4WtKlLnV7KuvzcT7x00qWk0vdfvria2uI2tvxBf2zrMn/f70qf49jXsfn+82lbhPlvyv7xP8t/2D7mqTxLnXXKru0+dc6svbG2m9NpdnHcp6A/q+k/80viR6s7PfOPpJG+MR/mv/MUzMe1pSsvl4ll9kLXCCpWtlVoU2UXc1oTKX7pq5jzFLWGM6P8aclPe1S94akb7nU/V7STcouLc/OLzuXthvdRv4t+iJJ+/jEL8p/pqvvNbR2zT3m31J2hWdKGev8l6RrfeIfyX9GubyCdutT6Tgu93isef0Pl9G3KyU95RN/bP5zztNlrFuxlnA75kRJ5+TfTuVSNzi/7P83SSe51HXIs8mxjdDWs5LGudR1yds4No9VS+qbZ3EdlV/OzD8Mt/OJf0rSj5Rld1V5n8+tuUQc8XNHY6h2qdst79OxJfFlyj5MmtILkk7O//s0ZftMkmZow6XcY5Rnuy51O0iq9om/RdKtyi5tviRplEvdTvkyXV3qGvsb7sbWaGPZpe5LLnVd8v/upux31lnKxuC8PGkYK2mHurbjE79Y0uL8t04pe/9q9JA012eFt99UVpfTVMxjLNegMexSt0v+javGMEkzteGkPt9ltSHHByuH/qbsp7aaYr2anyO6K/sAWeKyIrav2qu3O415/r5a0o9rzgsudZuUXNIvOgf10Ia7H75Vsq2mOi/OkDQs79t2kvYt+dunNfuhQv+tLOHdrybgUveNfLw9q/zYzROk+T7xS/XF139mybaa9HOhJSQOtyq7I+A1l7o3lRUybirpQUnv5X+7SyWXtcuscficT/xrksZLekVZYdStPvGv+8R/qqyY5BVJf1X2u5GUnUj/J/8G87qkG/IT8ZXKPiSnutS9lf+7qV2i7O6JFyTNLYn/XtLFLnWvu9QNKlrZlV/jUOpcSWfll22/qQ23vd6i7LfeKcouJdZk5mMkTXGpe13Zb+fX+8R/omxg35tv50VJu1bYn5aqMcfyCEmvluyrW33i/67s992R+Zg8QxvGal3OknRjftnZlcRvUnaimqLsvWiyqz51HGNSdkz+1qVussuKE02uuMahStnl2rfz/bW7soLlxcrG6JvKPuD+HtHV30iqcqn7R97fSXn/pyg7B7yj7CrQ8xHbag8abcz7rAD4fGXniH8oe98G5n8uOgddLukPLnWTJJXeRfeopGPzMXVQI71WKXvfP8hf1w2SXiv5283KPhPuqWsDrqDGwSe+WllydI1L3bR8H3xFWRJwuaQR+ev/pTYkSb+S9Iv8XFt61ewpSbvnr/+k8l9m3Zz3vv6l0CicMY8D0Jo4Yx4HoDVxBfM4IF5LuOIAAABaCRKH5jVeWVU80Fpdt7E7ADTQYmXnYlSInyoAAEA0rjgAAIBoTTKPg3OuVV7G6NOnTxD705/sGxHeeOONILbFFlsEsfXrwykk1q0Lpzu3rvysXh3eVt+lSxezPyed1OiFsxuN997Vv1TTaq1jGC0DY7h5jBo1KogdddRRQWzTTcOPugEDBgSxjz76KIhNmRJOK3HHHXdE9lDq0CG8y9n6XGhp6hrDXHEAAADRSBwAAEA0EgcAABCNxAEAAERrktsxW2tRzrnnnhvEbrjBftLwtGnTgtg222wTxKwimAULFgQxq4Bm9uzZQWyPPfYw+zN69Ogg9vbbb5vLtnQUlqG1YwyHNtkk/J762WefRa1bdN577rnngtibb74ZxD799NMgtnbt2iDmXPi29ejRI6aLkqT9998/etmWjuJIAADQKEgcAABANBIHAAAQjcQBAABEa5KZI1urESNGBLElS5aYy37yySdBbPPNNw9iq1atCmJr1qwJYlZxpDXDpLWuJO25555BrLUWRwJomRpS4Bi73NZbbx3E7r33XnPZyZMnB7HtttsuiC1dujSIWbPwWsXs1jm36HPh7rvvDmJnnHFGEGvtz4jiigMAAIhG4gAAAKKROAAAgGgkDgAAIBrFkSUGDRoUxMp5/KlV/NO5c+eo5WIfv209aluStt9++5guAkDFrHNXbMGkVTx+3nnnBbGxY8cGsZkzZ5r9sQoct9xyyyDWsWPHINa9e/cgZhUtWoWQ77//vtmfPn36BLEXXnghiJ199tlBzJrxsqXiigMAAIhG4gAAAKKROAAAgGgkDgAAIBqJAwAAiMZdFSWsOxbeeecdc9k5c+ZEbdOq0rWe+W7dQWFV837wwQdmO0V3WwBAU4qdSvqHP/xhEDvppJOC2OzZs4PYsmXLzG0uXrw4iA0ePDiIWX2cO3duEOvXr18Qmzp1ahBbsWKF2Z+qqqogZk1ZfeWVVwaxY4891txmbdbjCcq5+68xcMUBAABEI3EAAADRSBwAAEA0EgcAABCN4sgSVmGMVcgo2VNJ9+jRI4hZxZG9evUKYlaRjzWVq9WuZE+XDZTLGu/WGLYccsghQey5554LYs1dyFWqIa8P8YV51vTSo0aNCmLWVNKbbhp+LFnTQ0vS2rVrg9irr74axEaOHBnErLFgFUKuWrUqiO24445mfxYtWhTENttssyBmfQbceOONQez73/9+ENuYx08NrjgAAIBoJA4AACAaiQMAAIhG4gAAAKJRHFnCKvwpKo60CnisZa2ix969ewexrbfeOohZs0Fa7QKNJbZQ8Pjjjw9i1qx5++67bxB79tlnzW2+9NJLUW03RDmFkH379g1iY8eODWKTJk1qUJ9ak6LzYW2HH354ENtiiy2CmDV7o1VYOWTIELMda9+vXLkyiE2bNi2IbbnllkHMmmFyhx12CGJW4bpkj5np06cHMWvmyYEDB5rbjFHUn9hZPctur0m2CgAA2iQSBwAAEI3EAQAARCNxAAAA0ai0K2E92tqaDVKyi1Gs2c0efPDBIGYVy3zrW98KYtasah07djT7AzSnGTNmBLEDDjggiFmPFLaWk+yZJy+//PIgds011wSxyy67zNxmbdttt10QO/LII81lrdlYrZlb29MxaZ0jLfvss0/FbViFg9ZskJLUqVOnILbLLrsEMaso9sMPPwxiS5YsCWJWQWjR7I3W54JVdN+zZ88gZn3WDB06NIhZs1vGFq02Fq44AACAaCQOAAAgGokDAACIRuIAAACiURxZwipGLHp8qjXjmfVYbqsAZ/bs2UHsm9/8ZhD7+OOPg1jR42Wrq6vNONAUrGI1a6yfcsopQcwqaJPsgjHruLjqqquCmFUQd/vtt0dtzyr0lOyCujlz5gSx9jRzZKw99tgjiFmFg9ZsksuXLw9iRTMgWo+8fuWVV6LaiX3c9dKlS6PWlewxY30uWMWV1v4ZPnx4ELOKI5v70fBccQAAANFIHAAAQDQSBwAAEI3EAQAARKM4soT1OFZrpjjJni3Oeiyq9TjXDz74IIhZs4tZhZDdunUz+8PjtrGxWcW8v/71r4PYrFmzzPXvvPPOINalS5cgtv322wcxazbWUaNGBTFrVsKiWQAff/zxIPbcc8+Zy+KLPv300yC2evXqINa7d+8gZhVHWudHyS6atAocrfOjVeBoFVta48N69Ldkv+7+/fsHMavI1mrny1/+chAbP358EGuqx2cX4YoDAACIRuIAAACikTgAAIBoJA4AACAaFXUlrNm3ttxyS3NZqzjSKqS0irasGfYsViGkVfgjFc9kBrQ0Q4YMMeMPPPBAEPvJT34SxKwCxZtvvjmI7bDDDkFsp512CmJXXnml2R9rhleEunbtGsSs85RVfB5b1G3NqijZxbOxszJaj3yvqqoKYtbjrq0iyqJ2rCJ3a18sXrw4iFkzorYEXHEAAADRSBwAAEA0EgcAABCNxAEAAEQjcQAAANG4q6KENdVpp06dzGWtSlmrSteagrQhip67blXpom1zzgUxa3xYyxUt29htW5YuXWrGDzvssCB2/vnnB7GTTz45iB1xxBFBbNmyZUHsrrvuCmLl3D1hTX1cNGV1e7H11lsHMetuB+tOBOuuCmsa6rlz55ptW3d0WNMvW2Nz3bp1Qcy6W87aXtGU0wsXLgxi1h1v1ueKNSW3NbasPlqfPU2JKw4AACAaiQMAAIhG4gAAAKKROAAAgGgUR5b4+OOPg5hVYCXZRSuffPJJELOKZSxr164NYlZhZVGR0MyZM6PaQctnFeBZrKItS0OKIPX/2ru/1yzrP47jn29ImWxoLW0/xLa2mqTOYtTBEEHBo476A6KjBIMgRPwD/BM6MAlkHnSQg47CwCONIqqVicxfiJvR3Fwa27BmMYXv4Xf0fn6+vt29rWTPx+GL+7qv69593Zcfb173+yr1cuVK+Omnn0L2+uuvh6y7uztkfX19ITt8+HBDx7Pai5Bk586dIaPSI52vNFafRoXXrm90blJGRUg6HirI0+OoHF/bN42snp2dDRmVI2l0d0dHR8hGR0fxeJaL3zhIkqQ0Fw6SJCnNhYMkSUpz4SBJktIsRy5AE+1oSlcNTQPLFtNoqho9H5V3SskX6vTPyU5bbKSA1+hUOTqPspP4siXKRylrHjhwIGSffvppyLq6ukL2+eefp/fTCJoMuJq8/PLLqcc9/fTTIaOpnVSEpGmSpXDpkTI6r+l8bWpqChkV12kfpZTS2toask8++SRk+/btCxlNo6Rzi8rBliMlSdK/lgsHSZKU5sJBkiSluXCQJElpliMXoHIk3ba1ltOEsFqJ5u+oJETPV0OlHv27NDLBcdeuXSH7+uuvQ0ZFSLrFcSn5W7GvVBGSCmz0el599dWQtbS0hIyKxHT77YGBATweeo1btmwJ2fnz53H71YKmG9J1j8re4+PjIRseHg7ZO++8g/umab9PPBH/P0wlQyprEiot/vHHH/jYzs7OkB05ciRkb7zxRshoGiUVpWlS58mTJ/F4lovfOEiSpDQXDpIkKc2FgyRJSnPhIEmS0ixHLkBFrNoUP7pt7MTExKL3PTY2FjKaEEa32i6llJmZmUXvW/+cTZs2haynpydkr7zySsg+++yzkPX394eMCmg1NCUyO/Eyq1bWpLLaV199FbKXXnopZFRsps/o22+/HbLaZM3bt2+HbGpqKmSrvRxJt3mmgiIVJmnbS5cuhYymN9Zyet+zBV86bprqWztnaN80CZNuF0+fcdr31q1bcd8ryW8cJElSmgsHSZKU5sJBkiSluXCQJElpliMXuHv3bsimp6fxsVTG+vPPPxe978nJydTz0aS0Uhorqymn0ZLgnj17QrZx48aQUQFvcHAwZHQr3VOnToXs3XffxeP5/vvvQ9bIeUSTTp9//vmQUSGuFJ6IR5P46HHXrl0LGRXL6HNbK97R+00TYy9evIjbrxYbNmwIGZVsaXojTfxsb28PGV2bS+EyI6HjIXSMs7OzIatNTqXSJE0mvXLlSsj6+vpCRudm7RbjK8lvHCRJUpoLB0mSlObCQZIkpblwkCRJaZYjF6Db+tKtTkvhKXeNlFaoBPPUU0+FrHabbyqhaWlli4O1yYhUvKJiHT3u4MGDIaPpcx988EHI9u/fj8dDxbJvv/0WH/t3L7zwQsho8h0Vvtra2vA5qVh248aNkH388ccho2mDP/74Y8iuX78est9++w2Ph95vmvD666+/4varBd1Wm4qpzc3NIaPrHp2XdGvrUuqTfTNoWzoH6Tpcm+BLx06THi9fvhwy+vvQuUm3i19pfuMgSZLSXDhIkqQ0Fw6SJCnNhYMkSUpz4SBJktL8VcUCNNZ07dq1+FhqzlMbPotG4VKbl7JS8qNXldPT0xMyeo+oUb9v3z58zvv376f2Q+NxqQFObe3e3t6Q0WjpUkrZvHlzyOj8opG5tG/6tQS95m+++QaPZ2hoCPOlRL9KGh8fTz92ZGRkyY/pcffMM8+EjMbl07l19erVkNEv1mq/aKLRz9nR8NnrNb2W2vX29u3bIaPPOP3ih47nUX5hspL810aSJKW5cJAkSWkuHCRJUpoLB0mSlGY5cgEqwdDo1FJ4VCptnzUzMxMyKvTU7gNfO04tTn9/f8horDeNqN24cSM+J42ppSIYPY4KaDdv3gwZjail8dCl8Dj1999/P2RNTU2pbScmJkJ27NixkDU6MjdbfpuamgoZlTWpjFoKl/mo1Lba0XlIRT86r3/44YeQ7d69O2R0vS2F33d6P+l2ArQtved0ztTGytNzvvjiiyFrbW0NGf196LjpGOlxpTQ2kvv/8RsHSZKU5sJBkiSluXCQJElpLhwkSVKa5cgFqGBYu+86TRGsFWYyqFRDxZZasaxWmtTi0ERIKkxSUWlubg6fkwpjdM5R8ZDKT1R6pOOpFWfXrMl9/Gn7S5cuhWxwcDBkdA7XilxUaqPPRW2KYAZ9bmsTBKmwTJMBV5Pm5uaQZSce0vWRPitUBL5z5w4eD5WLqcxIx5MtytIEUdq2FP5M0WOfe+65kNHnjCYX02upFbJv3bqFeaP8xkGSJKW5cJAkSWkuHCRJUpoLB0mSlGY5cgEqQ1FWSinPPvtsyLq7u0OWnXJHGRVjakUumkSmxTtz5kzIqID05ptvhmzLli34nFRcpLLZtWvXQkbT+ah4SNMbaxNNaaJdZ2dnyM6ePRuyEydO4HNmLNc0u7+johp9fmply+vXry/5MT3uqLiY/ZtSEZLKiFQmrBVqad/Z22UTOjcfpaB79+7dkFG5squrK/Wc9LqpHNne3o7HYzlSkiT941w4SJKkNBcOkiQpzYWDJElKsxy5wNjYWMhqtySm2xdnb4FKZTUqDj3KbbWpMKOlNTQ0lMpo8mMppbz22msho5LUwMBAyLZt2xYyKs+SWhnxxo0bIfviiy9CRq/xcXD8+PGQvffeeyGrlVknJyeX/Jged5s2bQoZXXsoo6mbdI2jaZC1aay0fbZcmS1m0j6o8FgK3/6bPn/02aVtqehJx1grR547dw7zRvmvjSRJSnPhIEmS0lw4SJKkNBcOkiQpzXLkAn/99VfIalP3KKcpk9lbF1MBh/ZBBZpSSpmdnU3tR8uPbt1cSilffvllKmtkKqP+5+TJk6lMeXQ7aEKlPrpVPV0fqQBORcZSuHhI10gqI9J+qMz+5JNPpo+HSpN0PLRv+ptRqZO2pQm0y8lvHCRJUpoLB0mSlObCQZIkpblwkCRJaZYjH2J0dBRzKqNQ+SfrUW7dSmq3nZWkpULXvezkyAsXLoRs/fr1IaPiYa1kTvuhyZP0uPn5+dR+6HH37t3D46FyJBUu6XpNkzU7OjpCRuXIdevW4fEsF79xkCRJaS4cJElSmgsHSZKU5sJBkiSluXCQJElp/qriIWq/VqDmL40MpXGlhH6RQdvWRr62tbWl9iNJi0WN/vv374eMfknw888/h2zPnj0hq41sJ/TLM7p1AKHXMj09HTIa/U+/nqg9ln7RQdvT35H+naHXTP/2LCe/cZAkSWkuHCRJUpoLB0mSlObCQZIkpVmOfAgqtpRSSlNTU8io3JIdG/3dd9+lHlcr5dA93yVpKe3duzdkVISk6+aGDRtC9tZbb4Xsl19+CVntOkqlcCpX0nVz7dq1IXvw4EHI6LXUyoh07D09PSGjkdUjIyMho78tFSb7+/vxeJaL3zhIkqQ0Fw6SJCnNhYMkSUpz4SBJktIsRz7ERx99hPmOHTtCRpPRaBIZmZiYCNnRo0dD1tnZidt/+OGHqf1I0mIdOnQoZN3d3SGjMuOFCxdCdvr06ZD19vaGrKWlBY9nzZr4TxiVHqkc+fvvv4ds3bp1IaPC5NzcHB4PPefNmzdDNjw8HLL5+fmQbd++PWT0mq9cuYLHs1z8xkGSJKW5cJAkSWkuHCRJUpoLB0mSlPaf7GRDSZIkv3GQJElpLhwkSVKaCwdJkpTmwkGSJKW5cJAkSWkuHCRJUtp/AYwyf681o4qZAAAAAElFTkSuQmCC\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 10. Making a confusion matrix for further prediction evaluation \n",
        "\n",
        "A confusion matrix is a fantastic way of evaluating your classification models visually: https://www.learnpytorch.io/02_pytorch_classification/#9-more-classification-evaluation-metrics\n",
        "\n",
        "1. Make predictions with our trained model on the test dataset\n",
        "2. Make a confusion matrix `torchmetrics.ConfusionMatrix` - https://torchmetrics.readthedocs.io/en/stable/classification/confusion_matrix.html\n",
        "3. Plot the confusion matrix using `mlxtend.plotting.plot_confusion_matrix()` - http://rasbt.github.io/mlxtend/user_guide/plotting/plot_confusion_matrix/ "
      ],
      "metadata": {
        "id": "K8MYP8BU_XXQ"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Import tqdm.auto\n",
        "from tqdm.auto import tqdm \n",
        "\n",
        "\n",
        "# 1. Make predictions with trained model\n",
        "y_preds = []\n",
        "model_2.eval()\n",
        "with torch.inference_mode():\n",
        "  for X, y in tqdm(test_dataloader, desc=\"Making predictions...\"):\n",
        "    # Send the data and targets to target device\n",
        "    X, y = X.to(device), y.to(device)\n",
        "    # Do the forward pass\n",
        "    y_logit = model_2(X)\n",
        "    # Turn predictions from logits -> prediction probabilities -> prediction labels\n",
        "    y_pred = torch.softmax(y_logit.squeeze(), dim=0).argmax(dim=1)\n",
        "    # Put prediction on CPU for evaluation\n",
        "    y_preds.append(y_pred.cpu())\n",
        "\n",
        "# Concatenate list of predictions into a tensor\n",
        "# print(y_preds)\n",
        "y_pred_tensor = torch.cat(y_preds)\n",
        "y_pred_tensor"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 67,
          "referenced_widgets": [
            "9ab6303c323a4e23857567776bc0d20d",
            "b590346c9b654f42b2155bb94c16eae6",
            "3fec6a3f89c9452ebc9f3ebf6bface3a",
            "17df0b9ca3ca4cc1a26fe432c5997f3b",
            "825aae30ddcb49458ec0ec780342d013",
            "9b5740eb07014edb9a99b2fb863751f5",
            "49bd278666eb4bee88e1f7d358009589",
            "dbaedbc56495423dab883581485a9647",
            "1e8e68b35eb24de18b27030ebcedcb49",
            "7586aa9081074619b138b40a14537210",
            "bc263e0135f44bffa75ae95f63be97b7"
          ]
        },
        "id": "Dz5m-Y1ZB83q",
        "outputId": "9302ee70-0c8b-41fe-93cb-01f7add5fb2e"
      },
      "execution_count": 69,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "Making predictions...:   0%|          | 0/313 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "9ab6303c323a4e23857567776bc0d20d"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([9, 2, 1,  ..., 8, 1, 2])"
            ]
          },
          "metadata": {},
          "execution_count": 69
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "len(y_pred_tensor)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "LkuD_x0BC92H",
        "outputId": "67fe8e71-5336-4d22-d491-2fe1fca53aa4"
      },
      "execution_count": 70,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "10000"
            ]
          },
          "metadata": {},
          "execution_count": 70
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# See if required packages are installed and if not, install them...\n",
        "try:\n",
        "  import torchmetrics, mlxtend\n",
        "  print(f\"mlxtend version: {mlxtend.__version__}\")\n",
        "  assert int(mlxtend.__version__.split(\".\")[1] >= 19, \"mlxtend version should be 0.19.0 or higher\")\n",
        "except:\n",
        "  !pip install torchmetrics -U mlxtend \n",
        "  import torchmetrics, mlxtend\n",
        "  print(f\"mlxtend version: {mlxtend.__version__}\")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "8ZMedm2oBI5C",
        "outputId": "bbc1978f-fd86-4c76-dda3-91952a3797b6"
      },
      "execution_count": 71,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "mlxtend version: 0.19.0\n",
            "Requirement already satisfied: torchmetrics in /usr/local/lib/python3.7/dist-packages (0.8.0)\n",
            "Requirement already satisfied: mlxtend in /usr/local/lib/python3.7/dist-packages (0.19.0)\n",
            "Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from torchmetrics) (21.3)\n",
            "Requirement already satisfied: pyDeprecate==0.3.* in /usr/local/lib/python3.7/dist-packages (from torchmetrics) (0.3.2)\n",
            "Requirement already satisfied: torch>=1.3.1 in /usr/local/lib/python3.7/dist-packages (from torchmetrics) (1.10.0+cu111)\n",
            "Requirement already satisfied: numpy>=1.17.2 in /usr/local/lib/python3.7/dist-packages (from torchmetrics) (1.21.6)\n",
            "Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from torch>=1.3.1->torchmetrics) (4.1.1)\n",
            "Requirement already satisfied: matplotlib>=3.0.0 in /usr/local/lib/python3.7/dist-packages (from mlxtend) (3.2.2)\n",
            "Requirement already satisfied: scikit-learn>=0.20.3 in /usr/local/lib/python3.7/dist-packages (from mlxtend) (1.0.2)\n",
            "Requirement already satisfied: joblib>=0.13.2 in /usr/local/lib/python3.7/dist-packages (from mlxtend) (1.1.0)\n",
            "Requirement already satisfied: scipy>=1.2.1 in /usr/local/lib/python3.7/dist-packages (from mlxtend) (1.4.1)\n",
            "Requirement already satisfied: pandas>=0.24.2 in /usr/local/lib/python3.7/dist-packages (from mlxtend) (1.3.5)\n",
            "Requirement already satisfied: setuptools in /usr/local/lib/python3.7/dist-packages (from mlxtend) (57.4.0)\n",
            "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.7/dist-packages (from matplotlib>=3.0.0->mlxtend) (0.11.0)\n",
            "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib>=3.0.0->mlxtend) (1.4.2)\n",
            "Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib>=3.0.0->mlxtend) (2.8.2)\n",
            "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib>=3.0.0->mlxtend) (3.0.8)\n",
            "Requirement already satisfied: pytz>=2017.3 in /usr/local/lib/python3.7/dist-packages (from pandas>=0.24.2->mlxtend) (2022.1)\n",
            "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.7/dist-packages (from python-dateutil>=2.1->matplotlib>=3.0.0->mlxtend) (1.15.0)\n",
            "Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/lib/python3.7/dist-packages (from scikit-learn>=0.20.3->mlxtend) (3.1.0)\n",
            "mlxtend version: 0.19.0\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "import mlxtend\n",
        "print(mlxtend.__version__)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "uKq4cYLZB6LE",
        "outputId": "69a8b985-5498-41a9-bdb4-c943c034bb7e"
      },
      "execution_count": 78,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "0.19.0\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "class_names"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "cojhw0whFSn4",
        "outputId": "d832eda2-dd5b-4084-aedc-d79d2df8b514"
      },
      "execution_count": 79,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "['T-shirt/top',\n",
              " 'Trouser',\n",
              " 'Pullover',\n",
              " 'Dress',\n",
              " 'Coat',\n",
              " 'Sandal',\n",
              " 'Shirt',\n",
              " 'Sneaker',\n",
              " 'Bag',\n",
              " 'Ankle boot']"
            ]
          },
          "metadata": {},
          "execution_count": 79
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "y_pred_tensor[:10]"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "DuOuj3PoFaRx",
        "outputId": "74a00e18-1dd1-4aab-f295-930d8c863e8d"
      },
      "execution_count": 80,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([9, 2, 1, 1, 6, 1, 4, 6, 5, 7])"
            ]
          },
          "metadata": {},
          "execution_count": 80
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "test_data.targets"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "LNarlH6EFeje",
        "outputId": "acad2d31-02ac-4c7e-9e2c-8aaa840456cb"
      },
      "execution_count": 82,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([9, 2, 1,  ..., 8, 1, 5])"
            ]
          },
          "metadata": {},
          "execution_count": 82
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from torchmetrics import ConfusionMatrix\n",
        "from mlxtend.plotting import plot_confusion_matrix\n",
        "\n",
        "# 2. Setup confusion instance and compare predictions to targets\n",
        "confmat = ConfusionMatrix(num_classes=len(class_names))\n",
        "confmat_tensor = confmat(preds=y_pred_tensor,\n",
        "                         target=test_data.targets)\n",
        "\n",
        "# 3. Plot the confusion matrix\n",
        "fig, ax = plot_confusion_matrix(\n",
        "    conf_mat=confmat_tensor.numpy(), # matplotlib likes working with numpy\n",
        "    class_names=class_names,\n",
        "    figsize=(10, 7)\n",
        ")"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 477
        },
        "id": "BUnYpPTNEfbH",
        "outputId": "19b99bbf-b4d9-4d6b-abf4-8c8aab85728d"
      },
      "execution_count": 85,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 720x504 with 1 Axes>"
            ],
            "image/png": "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\n"
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 11. Save and load best performing model"
      ],
      "metadata": {
        "id": "QG06n7YCFmm0"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from pathlib import Path\n",
        "\n",
        "# Create model dictory path\n",
        "MODEL_PATH = Path(\"models\")\n",
        "MODEL_PATH.mkdir(parents=True,\n",
        "                 exist_ok=True)\n",
        "\n",
        "# Create model save\n",
        "MODEL_NAME = \"03_pytorch_computer_vision_model_2.pth\"\n",
        "MODEL_SAVE_PATH = MODEL_PATH / MODEL_NAME\n",
        "\n",
        "# Save the model state dict\n",
        "print(f\"Saving model to: {MODEL_SAVE_PATH}\")\n",
        "torch.save(obj=model_2.state_dict(),\n",
        "           f=MODEL_SAVE_PATH)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ZDkDs2YdFns_",
        "outputId": "61812cdc-ddbf-4a05-dea7-a416de703e7a"
      },
      "execution_count": 88,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Saving model to: models/03_pytorch_computer_vision_model_2.pth\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "image_shape = [1, 28, 28]"
      ],
      "metadata": {
        "id": "4PRZao4MIwD4"
      },
      "execution_count": 90,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Create a new instance\n",
        "torch.manual_seed(42)\n",
        "\n",
        "loaded_model_2 = FashionMNISTModelV2(input_shape=1,\n",
        "                                     hidden_units=10,\n",
        "                                     output_shape=len(class_names))\n",
        "\n",
        "# Load in the save state_dict()\n",
        "loaded_model_2.load_state_dict(torch.load(f=MODEL_SAVE_PATH))\n",
        "\n",
        "# Send the model to the target device\n",
        "loaded_model_2.to(device)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "yYNHaywoH3qe",
        "outputId": "d5ca217b-7dc7-44c1-c39a-cda31ee32cbc"
      },
      "execution_count": 91,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "FashionMNISTModelV2(\n",
              "  (conv_block_1): Sequential(\n",
              "    (0): Conv2d(1, 10, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "    (1): ReLU()\n",
              "    (2): Conv2d(10, 10, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "    (3): ReLU()\n",
              "    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
              "  )\n",
              "  (conv_block_2): Sequential(\n",
              "    (0): Conv2d(10, 10, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "    (1): ReLU()\n",
              "    (2): Conv2d(10, 10, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
              "    (3): ReLU()\n",
              "    (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
              "  )\n",
              "  (classifier): Sequential(\n",
              "    (0): Flatten(start_dim=1, end_dim=-1)\n",
              "    (1): Linear(in_features=490, out_features=10, bias=True)\n",
              "  )\n",
              ")"
            ]
          },
          "metadata": {},
          "execution_count": 91
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Evaluate loaded model\n",
        "torch.manual_seed(42)\n",
        "\n",
        "loaded_model_2_results = eval_model(\n",
        "    model=loaded_model_2,\n",
        "    data_loader=test_dataloader,\n",
        "    loss_fn=loss_fn,\n",
        "    accuracy_fn=accuracy_fn\n",
        ")\n",
        "\n",
        "loaded_model_2_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 102,
          "referenced_widgets": [
            "eddf525370cc47dc8c39a683157d1349",
            "3dc582db727f42cb952084739ee3fcf7",
            "b89ea56117304c299214076f7acff99f",
            "3c00bb6d32ef4031b01a756bf3eb9a76",
            "a1ea8ec4a407495aa9395f279889cff5",
            "90e5c0cf18c34a88bfc7275bb5fc96a2",
            "e1b43099620b497eacc22b708bf4c2ff",
            "1560cfbd3ba641bdb8acc89f7f17fb2d",
            "e30a4eed4e9145dc9597cb55100bec57",
            "7f792d4491084829999e5540094cb85d",
            "898759c1d24645e2b6678011cb00a76e"
          ]
        },
        "id": "8Thv6LNnH3nq",
        "outputId": "8364961d-ffa1-4e1a-9343-94d7425e43e5"
      },
      "execution_count": 93,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "  0%|          | 0/313 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "eddf525370cc47dc8c39a683157d1349"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'model_acc': 88.56829073482429,\n",
              " 'model_loss': 0.31358689069747925,\n",
              " 'model_name': 'FashionMNISTModelV2'}"
            ]
          },
          "metadata": {},
          "execution_count": 93
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "model_2_results"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "R3m5bFynJJYu",
        "outputId": "f0c7d54c-ffc7-4781-c142-df5470c8a126"
      },
      "execution_count": 92,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'model_acc': 88.56829073482429,\n",
              " 'model_loss': 0.31358689069747925,\n",
              " 'model_name': 'FashionMNISTModelV2'}"
            ]
          },
          "metadata": {},
          "execution_count": 92
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Check if model results are close to each other\n",
        "torch.isclose(torch.tensor(model_2_results[\"model_loss\"]),\n",
        "              torch.tensor(loaded_model_2_results[\"model_loss\"]),\n",
        "              atol=1e-02)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Vuwa9ZvjH3k3",
        "outputId": "f066edb9-c985-4314-9ad8-4d2b54a83b24"
      },
      "execution_count": 94,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor(True)"
            ]
          },
          "metadata": {},
          "execution_count": 94
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Exercises\n",
        "\n",
        "* See here for exercises and extra-curriculum: https://www.learnpytorch.io/03_pytorch_computer_vision/#exercises \n"
      ],
      "metadata": {
        "id": "TaiwA_vjH3iZ"
      }
    },
    {
      "cell_type": "code",
      "source": [
        ""
      ],
      "metadata": {
        "id": "MgmFkG5gL8R8"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}